Scanner(ReadableByteChannel source, String charset)

Scanner(String source),

где source – источник входных данных, а charset– кодировка.

Объект класса Scanner читает лексемы из источника, указанного в конструкторе, например из строки или файла. Лексема – это набор данных, выделенный набором разделителей (по умолчанию пробелами). В случае ввода из консоли следует определить объект:

Scanner con = new Scanner(System.in);

После создания объекта его используют для ввода, например целых чисел, следующим образом:

write(con.hasNextInt()) {

int n = con.nextInt();

}

В классе Scanner определены группы методов, проверяющих данные заданного типа на доступ для ввода. Для проверки наличия произвольной лексемы используется метод hasNext(). Проверка конкретного типа производится с помощью одного из методов boolean hasNextТип() или boolean hasNextТип(int radix), где radix– основание системы счисления. Например, вызов метода hasNextInt() возвращает true, только если следующая входящая лексема – целое число. Если данные указанного типа доступны, они считываются с помощью одного из методов Тип nextТип(). Произвольная лексема считывается методом String next(). После извлечения любой лексемы текущий указатель устанавливается перед следующей лексемой.

// пример # 10 : разбор файла: ScannerLogic.java : ScannerDemo.java

package chap09;

import java.io.*;

import java.util.Scanner;

class ScannerLogic {

static String filename = "scan.txt";

public static void scanFile() {

try {

FileReader fr =

new FileReader(filename);

Scanner scan = new Scanner(fr);

while (scan.hasNext()) {//чтение из файла

if (scan.hasNextInt())

System.out.println(

scan.nextInt() + ":int");

else if (scan.hasNextDouble())

System.out.println(

scan.nextDouble() + ":double");

else if (scan.hasNextBoolean())

System.out.println(

scan.nextBoolean() + ":boolean");

Else

System.out.println(

scan.next() + ":String");

}

} catch (FileNotFoundException e) {

System.err.println(e);

}

}

public static void makeFile() {

try {

FileWriter fw =

new FileWriter(filename);//создание потока для записи

fw.write("2 Java 1,5 true 1.6 ");//запись данных

fw.close();

} catch (IOException e) {

System.err.println(e);

}

}

}

public class ScannerDemo {

public static void main(String[] args) {

ScannerLogic.makeFile();

ScannerLogic.scanFile();

}

}

В результате выполнения программы будет выведено:

Int

Java:String

Double

true:boolean

String

Процедура проверки типа реализована при с помощью методов hasNextТип(). Такой подход предпочтителен из-за отсутствия возможности возникновения исключительной ситуации, так как ее обработка требует на порядок больше ресурсов, чем нормальное течение программы. Для чтения строки из потока ввода применяются методы next() или nextLine().

Объект класса Scanner определяет границы лексемы, основываясь на наборе разделителей. Можно задавать разделители с помощью метода useDelimiter(Pattern pattern)или useDelimiter(String
pattern), где pattern содержит набор разделителей.

/* пример # 11 : применение разделителей: ScannerDelimiterDemo.java*/

package chapt09;

import java.util.Scanner;

public class ScannerDelimiterDemo {

public static void main(String args[]) {

double sum = 0.0;

Scanner scan =

new Scanner("1,3;2,0; 8,5; 4,8; 9,0; 1; 10");

scan.useDelimiter(";\\s*");

while (scan.hasNext()) {

if (scan.hasNextDouble())

sum += scan.nextDouble();

else System.out.println(scan.next());

}

System.out.printf("Сумма чисел = " + sum);

}

}

}

В результате выполнения программы будет выведено:

Сумма чисел = 36.6

Использование шаблона "; *"указывает объекту класса Scanner, что ‘;’ и ноль или более пробелов следует рассмативать как разделитель.

Метод String findInLine(Pattern pattern) или String
findInLine(String pattern)ищет заданный шаблон в следующей строке текста. Если шаблон найден, соответствующая ему подстрока извлекается из строки ввода. Если совпадений не найдено, то возвращается null.

МетодыString findWithinHorizon(Pattern pattern, int count)и String findWithinHorizon(String pattern, int count) производят поиск заданного шаблона в ближайших count символах. Можно пропустить образец с помощью метода skip(Pattern pattern).

Если в строке ввода найдена подстрока, соответствующая образцу pattern, метод skip() просто перемещается за нее в строке ввода и возвращает ссылку на вызывающий объект. Если подстрока не найдена, метод skip() генерирует исключение NoSuchElementException.

Архивация

Для хранения классов языка Java и связанных с ними ресурсов в языке Java используются сжатые архивные jar-файлы.

Для работы с архивами в спецификации Java существуют два пакета – java.util.zipи java.util.jar соответственно для архивов zip и jar. Различие форматов jar и zip заключается только в расширении архива zip. Пакет java.util.jar аналогичен пакету java.util.zip, за исключением реализации конструкторов и метода void putNextEntry(ZipEntry e)класса JarOutputStream. Ниже будет рассмотрен только пакет java.util.jar. Чтобы переделать все примеры на использование zip-архива, достаточно всюду
в коде заме­нить Jar на Zip.

Пакет java.util.jar позволяет считывать, создавать и изменять файлы форматов jar, а также вычислять контрольные суммы входящих потоков данных.

Класс JarEntry (подкласс ZipEntry) используется для предоставления доступа к записям jar-файла. Наиболее важными методами класса являются:

void setMethod(int method)– устанавливает метод сжатия записи;

int getMethod()– возвращает метод сжатия записи;

void setComment(String comment)– устанавливает комментарий записи;

String getComment()– возвращает комментарий записи;

void setSize(long size) – устанавливает размер несжатой записи;

long getSize() – возвращает размер несжатой записи;

long getCompressedSize()– возвращает размер сжатой записи;

У класса JarOutputStream существует возможность записи данных в поток вывода в jar-формате. Он переопределяет метод write() таким образом, чтобы любые данные, записываемые в поток, предварительно сжимались. Основными методами данного класса являются:

void setLevel(int level)– устанавливает уровень сжатия. Чем больше уровень сжатия, тем медленней происходит работа с таким файлом;

void putNextEntry(ZipEntry e)– записывает в поток новую jar-запись. Этот метод переписывает данные из экземпляра JarEntry в поток вывода;

void closeEntry()– завершает запись в поток jar-записи и заносит дополнительную информацию о ней в поток вывода;

void write(byte b[], int off, int len)– записывает данные из буфера b начиная с позиции off длиной len в поток вывода;

void finish()– завершает запись данных jar-файла в поток вывода без закрытия потока;

void close()– закрывает поток записи.

/* пример # 12 : создание jar-архива: PackJar.java */

package chapt09;

importjava.io.FileInputStream;

importjava.io.FileNotFoundException;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.util.jar.JarEntry;

importjava.util.jar.JarOutputStream;

importjava.util.zip.Deflater;

public classPackJar {

public static voidpack(String[] filesToJar,

String jarFileName, byte[] buffer) {

try {

JarOutputStream jos =

newJarOutputStream(

new FileOutputStream(jarFileName));

// метод сжатия

jos.setLevel(Deflater.DEFAULT_COMPRESSION);

for (int i = 0; i < filesToJar.length; i++) {

System.out.println(i);

jos.putNextEntry(new JarEntry(filesToJar[i]));

FileInputStream in =

new FileInputStream(filesToJar[i]);

int len;

while ((len = in.read(buffer)) > 0)

jos.write(buffer, 0, len);

jos.closeEntry();

in.close();

}

jos.close();

} catch (IllegalArgumentException e) {

e.printStackTrace();

System.err.println("Некорректный аргумент");

} catch (FileNotFoundException e) {

e.printStackTrace();

System.err.println("Файл не найден");

} catch (IOException e) {

e.printStackTrace();

System.err.println("Ошибка доступа");

}

}

public static void main(String[] args) {

System.out.println("Создание jar-архива");

// массив файлов для сжатия

String[] filesToJar = new String[2];

filesToJar[0] = "chapt09//UseJar.java";

filesToJar[1] = "chapt09//UseJar.class";

byte[] buffer = new byte[1024];

// имя полученного архива

String jarFileName = "example.jar";

pack(filesToJar, jarFileName, buffer);

}

}

Класс JarFile обеспечивает гибкий доступ к записям, хранящимся в jar-файле. Это очень эффективный способ, поскольку доступ к данным осуществляется гораздо быстрее, чем при считывании каждой отдельной записи. Единственным недостатком является то, что доступ может осуществляться только для чтения. Метод entries() извлекает все записи из jar-файла. Этот метод возвращает список экземпляров JarEntry – по одной для каждой записи в jar- файле. Метод getEntry(String name)извлекает запись по имени. Метод getInputStream()создает поток ввода для записи. Этот метод возвращает поток ввода, который может использоваться приложением для чтения данных записи.

Класс JarInputStream читает данные в jar-формате из потока ввода. Он переопределяет метод read() таким образом, чтобы любые данные, считываемые из потока, предварительно распаковывались.

/* пример # 13 : чтение jar-архива: UnPackJar.java */

package chapt09;

import java.io.*;

import java.util.Enumeration;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

public class UnPackJar {

private File destFile;

// размер буфера для распаковки

public final int BUFFER = 2048;

public void unpack(String destinationDirectory,

String nameJar) {

File sourceJarFile = new File(nameJar);

try {

File unzipDestinationDirectory =

new File(destinationDirectory);

// открытие zip-архива для чтения

JarFile jFile = new JarFile(sourceJarFile);

Enumeration jarFileEntries = jFile.entries();

while (jarFileEntries.hasMoreElements()) {

// извлечение текущей записи из архива

JarEntry entry =

(JarEntry) jarFileEntries.nextElement();

String entryname = entry.getName();

//entryname = entryname.substring(2);

System.out.println("Extracting: " + entry);

destFile =

new File(unzipDestinationDirectory, entryname);

// определение каталога

File destinationParent =

destFile.getParentFile();

// создание структуры каталогов

destinationParent.mkdirs();

// распаковывание записи, если она не каталог

if (!entry.isDirectory()) {

writeFile(jFile, entry);

}

}

jFile.close();

} catch (IOException ioe) {

ioe.printStackTrace();

}

}

private void writeFile(JarFile jFile, JarEntry entry)

throws IOException {

BufferedInputStream is =

new BufferedInputStream(

jFile .getInputStream(entry));

int currentByte;

byte data[] = new byte[BUFFER];

// запись файла на диск

BufferedOutputStream dest =

new BufferedOutputStream(

new FileOutputStream(destFile), BUFFER);

while ((currentByte = is.read(data, 0, BUFFER)) > 0){

dest.write(data, 0, currentByte);

}

dest.flush();

dest.close();

is.close();

}

public static void main(String[] args) {

System.out.println(

"Извлечение данных из jar-архива");

// расположение и имя архива

String nameJar = "c:\\work\\example.jar";

// куда файлы будут распакованы

String destination = "c:\\temp\\";

new UnPackJar().unpack(destination, nameJar);

}

}

Задания к главе 9

Вариант A

В следующих заданиях требуется ввести последовательность строк из текстового потока и выполнить указанные действия. При этом могут рассматриваться два варианта:

· каждая строка состоит из одного слова;

· каждая строка состоит из нескольких слов.

Имена входного и выходного файлов, а также абсолютный путь к ним могут быть введены как параметры командной строки или храниться в файле.

1. В каждой строке найти и удалить заданную подстроку.

2. В каждой строке стихотворения Александра Блока найти и заменить заданную подстроку на подстроку иной длины.

3. В каждой строке найти слова, начинающиеся с гласной буквы.

4. Найти и вывести слова текста, для которых последняя буква одного слова совпадает с первой буквой следующего слова.

5. Найти в строке наибольшее число цифр, идущих подряд.

6. В каждой строке стихотворения Сергея Есенина подсчитать частоту повторяемости каждого слова из заданного списка и вывести эти слова в порядке возрастания частоты повторяемости.

7. В каждом слове сонета Вильяма Шекспира заменить первую букву слова на прописную.

8. Определить частоту повторяемости букв и слов в стихотворении Александра Пушкина.

Вариант B

Выполнить задания из варианта B главы 4, сохраняя объекты приложения в одном или нескольких файлах с применением механизма сериализации. Объекты могут содержать поля, помеченные как static, а также transient. Для изменения информации и извлечения информации в файле создать специальный класс-коннектор с необходимыми для выполнения этих задач методами.

Вариант С

При выполнении следующих заданий для вывода результатов создавать новую директорию и файл средствами класса File.

1. Создать и заполнить файл случайными целыми числами. Отсортировать содержимое файла по возрастанию.

2. Прочитать текст Java-программы и все слова public в объявлении атрибутов и методов класса заменить на слово private.

3. Прочитать текст Java-программы и записать в другой файл в обратном порядке символы каждой строки.

4. Прочитать текст Java-программы и в каждом слове длиннее двух символов все строчные символы заменить прописными.

5. В файле, содержащем фамилии студентов и их оценки, записать прописными буквами фамилии тех студентов, которые имеют средний балл более “7”.

6. Файл содержит символы, слова, целые числа и числа с плавающей запятой. Определить все данные, тип которых вводится из командной строки.

7. Из файла удалить все слова, содержащие от трех до пяти символов, но при этом из каждой строки должно быть удалено только максимальное четное количество таких слов.

8. Прочитать текст Java-программы и удалить из него все “лишние” пробелы и табуляции, оставив только необходимые для разделения операторов.

9. Из текста Java-программы удалить все виды комментариев.

10. Прочитать строки из файла и поменять местами первое и последнее слова в каждой строке.

11. Ввести из текстового файла, связанного с входным потоком, последовательность строк. Выбрать и сохранить m последних слов в каждой из последних n строк.

12. Из текстового файла ввести последовательность строк. Выделить отдельные слова, разделяемые пробелами. Написать метод поиска слова по образцу-шаблону. Вывести найденное слово в другой файл.

13. Сохранить в файл, связанный с выходным потоком, записи о телефонах и их владельцах. Вывести в файл записи, телефоны которых начинаются на k и на j.

14. Входной файл содержит совокупность строк. Строка файла содержит строку квадратной матрицы. Ввести матрицу в двумерный массив (размер матрицы найти). Вывести исходную матрицу и результат ее транспонирования.

15. Входной файл хранит квадратную матрицу по принципу: строка представляет собой число. Определить размерность. Построить 2-мерный массив, содержащий матрицу. Вывести исходную матрицу и результат ее поворота на 90 градусов по часовой стрелке.

16. В файле содержится совокупность строк. Найти номера строк, совпадающих с заданной строкой. Имя файла и строка для поиска – аргументы командной строки. Вывести строки файла и номера строк, совпадающих с заданной.

Тестовые задания к главе 9

Вопрос 9.1.

Можно ли изменить корневой каталог, в который вкладываются все пользовательские каталоги, используя объект myfile класса File? Если это возможно, то с помощью какой инструкции?

1) myfile.chdir("NAME");

2) myfile.cd("NAME");

3) myfile.changeDir("NAME");

4) методы класса File не могут изменять корневой каталог.

Вопрос 9.2.

Экземпляром какого класса является поле System.in?

1) java.lang.System;

2) java.io.InputStream;

3) java.io.BufferedInputStream;

4) java.io.PrintStream;

5) java.io.Reader.

Вопрос 9.3.

Какие из следующих операций можно выполнить применительно к файлу на диске с помощью методов объекта класса File?

1) добавить запись в файл;

2) вернуть имя родительской директории;

3) удалить файл;

4) определить, текстовую или двоичную информацию содержит файл.

Вопрос 9.4.

Какой абстрактный класс является суперклассом для всех классов, используемых для чтения байтов?

1) Reader;

2) FileReader;

3) ByteReader;

4) InputStream;

5) FileInputStream.

Вопрос 9.5.

При объявлении какого из приведенных понятий может быть использован модификатор transient?

1) класса;

2) метода;

3) поля класса;

4) локальной переменной;

5) интерфейса.

 
Глава 10

КОЛЛЕКЦИИ

Общие определения

Коллекции – это хранилища, поддерживающие различные способы накопления и упорядочения объектов с целью обеспечения возможностей эффективного доступа к ним. Они представляют собой реализацию абстрактных типов (структур) данных, поддерживающих три основные операции:

· добавление нового элемента в коллекцию;

· удаление элемента из коллекции;

· изменение элемента в коллекции.

В качестве других операций могут быть реализованы следующие: просмотреть элементы, подсчитать их количество и др.

Применение коллекций обусловливается возросшими объемами обрабатываемой информации. Когда счет используемых объектов идет на сотни тысяч, массивы не обеспечивают ни должной скорости, ни экономии ресурсов. Например, процессор UltraSPARC T1 тестировался на обработке информации для электронного магазина, содержащего около 40 тысяч товаров и 125 миллионов клиентов, сделавших 400 миллионов заказов.

Примером коллекции является стек (структура LIFO – Last In First Out), в котором всегда удаляется объект, вставленный последним. Для очереди (структура FIFO – First In First Out) используется другое правило удаления: всегда удаляется элемент, вставляемый первым. В абстрактных типах данных существует несколько видов очередей: двусторонние очереди, кольцевые очереди, обобщенные очереди, в которых запрещены повторяющиеся элементы. Стеки и очереди могут быть реализованы как на базе массива, так и на базе связного списка.

Коллекции в языке Java объединены в библиотеке классов java.utilи представляют собой контейнеры для хранения и манипулирования объектами. До появления Java 2 эта библиотека содержала классы только для работы с простейшими структурами данных: Vector, Stack, Hashtable, BitSet, а также интерфейс Enumeration для работы с элементами этих классов. Коллекции, появившиеся в Java 2, представляют общую технологию хранения и доступа к объектам. Скорость обработки коллекций повысилась по сравнению с предыдущей версией языка за счет отказа от их потокобезопасности. Поэтому если объект коллекции может быть доступен из различных потоков, что наиболее естественно для распределенных приложений, следует использовать коллекции из Java 1.

Так как в коллекциях при практическом программировании хранится набор ссылок на объекты одного типа, следует обезопасить коллекцию от появления ссылок на другие не разрешенные логикой приложения типы. Такие ошибки при использовании нетипизированных коллекций выявляются на стадии выполнения, что повышает трудозатраты на исправление и верификацию кода. Поэтому начиная с версии 5.0 коллекции стали типизированными.

Более удобным стал механизм работы с коллекциями, а именно:

· предварительное сообщение компилятору о типе ссылок, которые будут храниться в коллекции, при этом проверка осуществляется на этапе компиляции;

· отсутствие необходимости постоянно преобразовывать возвращаемые по ссылке объекты (тип Object) к требуемому типу.

Структура коллекций характеризует способ, с помощью которого программы Java обрабатывают группы объектов. Так как Object – суперкласс для всех классов, то в коллекции можно хранить объекты любого типа, кроме базовых. Коллекции – это динамические массивы, связные списки, деревья, множества, хэш-таблицы, стеки, очереди.

Интерфейсы коллекций:

Map<K,V> – карта отображения вида “ключ-значение”;

Collection<E> – вершина иерархии остальных коллекций;

List<E> – специализирует коллекции для обработки списков;

Set<E> – специализирует коллекции для обработки множеств, содержащих уникальные элементы.

Все классы коллекций реализуют также интерфейсы Serializable, Cloneable (кроме WeakHashMap). Кроме того, классы, реализующие интерфейсы List<E> и Set<E>, реализуют также интерфейс Iterable<E>.

В интерфейсе Collection<E> определены методы, которые работают на всех коллекциях:

boolean add(E obj) – добавляет objк вызывающей коллекции и возвращает true, если объект добавлен, и false, если obj уже элемент коллекции;

boolean addAll(Collection<? extends E> c) – добавляет все элементы коллекции к вызывающей коллекции;

void clear() – удаляет все элементы из коллекции;

boolean contains(Object obj) – возвращает true, если вызывающая коллекция содержит элементobj;

boolean equals(Object obj) – возвращает true, если коллекции эквивалентны;

boolean isEmpty()– возвращает true, если коллекция пуста;

Iterator<E> iterator() – извлекает итератор;

boolean remove(Object obj) – удаляет obj из коллекции;

int size() – возвращает количество элементов в коллекции;

Object[] toArray() – копирует элементы коллекции в массив объектов;

<T> T[] toArray(T a[]) – копирует элементы коллекции в массив объектов определенного типа.

Для работы с элементами коллекции применяются следующие интерфейсы:

Comparator<T> – для сравнения объектов;

Iterator<E>, ListIterator<E>, Map.Entry<K,V> – для перечисления и доступа к объектам коллекции.

Интерфейс Iterator<E> используется для построения объектов, которые обеспечивают доступ к элементам коллекции. К этому типу относится объект, возвращаемый методом iterator(). Такой объект позволяет просматривать содержимое коллекции последовательно, элемента за элементом. Позиции итератора располагаются в коллекции между элементами. В коллекции, состоящей из N элементов, существует N+1 позиций итератора.

Методы интерфейса Iterator<E>:

boolean hasNext()– проверяет наличие следующего элемента, а в случае его отсутствия (завершения коллекции) возвращает false. Итератор при этом остается неизменным;

E next()– возвращает объект, на который указывает итератор, и передвигает текущий указатель на следующий, предоставляя доступ к следующему элементу. Если следующий элемент коллекции отсутствует, то метод next()генерирует исключение NoSuchElementException;

void remove()– удаляет объект, возвращенный последним вызовом метода next().

ИнтерфейсListIterator<E> расширяет интерфейсIterator<E>
и предназначен в основном для работы со списками. Наличие методов
E previous(), int previousIndex() и boolean hasPrevious() обеспечивает обратную навигацию по списку. Метод int nextIndex() возвращает номер следующего итератора. Метод void add(E obj) позволяет вставлять элемент в список текущей позиции. Вызов методаvoid set(E obj) производит замену текущего элемента списка на объект, передаваемый методу в качестве
параметра.

Интерфейс Map.Entry предназначен для извлечения ключей и значений карты с помощью методов K getKey() и V getValue() соответственно. Вызов метода V setValue(V value) заменяет значение, ассоциированное с текущим ключом.

Списки

Рис. 10.1. Иерархия наследования списков

Класс ArrayList<E> – динамический массив объектных ссылок. Расширяет класс AbstractList<E>и реализует интерфейс List<E>. Класс имеет конструкторы:

ArrayList()

ArrayList(Collection <? extends E> c)

ArrayList(int capacity)

Практически все методы класса являются реализацией абстрактных методов из суперклассов и интерфейсов. Методы интерфейса List<E> позволяют вставлять и удалять элементы из позиций, указываемых через отсчитываемый от нуля индекс:

void add(int index, E element) – вставляет elementв позицию, указанную в index;

void addAll(int index, Collection<? extends E> c) – вставляет в вызывающий список все элементы коллекции с,начиная с позиции index;

E get(int index) – возвращает элемент в виде объекта из позиции
index;

int indexOf(Object ob) – возвращает индекс указанного объекта;

E remove(int index) – удаляет объект из позиции index;

E set(int index, E element) – заменяет объект в позиции index, возвращает при этом удаляемый элемент;

List<E> subList(int fromIndex, int toIndex) – извлекает часть коллекции в указанных границах.

Удаление и добавление элементов для такой коллекции представляет собой ресурсоемкую задачу, поэтому объект ArrayList<E> лучше всего подходит для хранения неизменяемых списков.

/* пример # 1 : создание параметризованной коллекции : DemoGeneric.java */

packagechapt10;

import java.util.*;

public class DemoGeneric {

public static void main(String args[]) {

ArrayList<String> list = new ArrayList<String>();

// ArrayList<int> b = new ArrayList<int>(); // ошибка компиляции

list.add("Java");

list.add("Fortress");

String res = list.get(0);/* компилятор “знает”

тип значения */

// list.add(new StringBuilder("C#")); // ошибка компиляции

// компилятор не позволит добавить “посторонний” тип

System.out.print(list);

}

}

В результате будет выведено:

[Java, Fortress]

В данной ситуации не создается новый класс для каждого конкретного типа и сама коллекция не меняется, просто компилятор снабжается информацией о типе элементов, которые могут храниться в list. При этом параметром коллекции может быть только объектный тип.

Следует отметить, что указывать тип следует при создании ссылки, иначе будет позволено добавлять объекты всех типов.

/* пример # 2 : некорректная коллекция : UncheckCheck.java */

packagechapt10;

import java.util.*;

public class UncheckCheck {

public static void main(String args[]) {

ArrayList list = new ArrayList();

list.add(71);

list.add(new Boolean("TruE"));

list.add("Java 1.6.0");

// требуется приведение типов

int i = (Integer)list.get(0);

boolean b = (Boolean)list.get(1);

String str = (String)list.get(2);

for (Object ob : list)

System.out.println("list " + ob);

ArrayList<Integer> s = new ArrayList<Integer>();

s.add(71);

s.add(92);

// s.add("101");// ошибка компиляции: s параметризован

for (Integer ob : s)

System.out.print("int " + ob);

}

}

В результате будет выведено:

List 71

List true

List Java 1.6.0

Int 71

Int 92

Чтобы параметризация коллекции была полной, необходимо указывать параметр и при объявлении ссылки, и при создании объекта.

Объект типа Iterator может использоваться для последовательного перебора элементов коллекции. Ниже приведен пример заполнения списка псевдослучайными числами, подсчет с помощью итератора количества положитель­ных и удаление из списка неположительных значений.

/* пример # 3 : работа со списком : DemoIterator.java */

package chapt10;

import java.util.*;

public class DemoIterator {

public static void main(String[] args) {

ArrayList<Double> c =

new ArrayList<Double>(7);

for(int i = 0 ;i < 10; i++) {

double z = new Random().nextGaussian();

c.add(z);//заполнение списка

}

//вывод списка на консоль

for(Double d: c) {

System.out.printf("%.2f ",d);

}

int positiveNum = 0;

int size = c.size();//определение размера коллекции

//извлечение итератора

Iterator<Double> it = c.iterator();

//проверка существования следующего элемента

while(it.hasNext()) {

//извлечение текущего элемента и переход к следующему

if (it.next() > 0) positiveNum++;

else it.remove();//удаление неположительного элемента

}

System.out.printf("%nКоличество положительных: %d ",

positiveNum);

System.out.printf("%nКоличество неположительных: %d ",

size - positiveNum);

System.out.println("\nПоложительная коллекция");

for(Double d : c) {

System.out.printf("%.2f ",d);

}

}

}

В результате на консоль будет выведено:

0,69 0,33 0,51 -1,24 0,07 0,46 0,56 1,26 -0,84 -0,53

Количество положительных: 7

Количество отрицательных: 3

Положительная коллекция

0,69 0,33 0,51 0,07 0,46 0,56 1,26

Для доступа к элементам списка может также использоваться интерфейс
ListIterator<E>, который позволяет получить доступ сразу в необходимую программисту позицию списка. Такой способ доступа возможен только для списков.

/* пример # 4 : замена, удаление и поиск элементов : DemoListMethods.java */

packagechapt10;

import java.util.*;

public class DemoListMethods {

public static void main(String[] args) {

ArrayList<Character> a =

new ArrayList<Character>(5);

System.out.println("коллекция пуста: "

+ a.isEmpty());

for (char c = 'a'; c < 'h'; ++c) {

a.add(c);

}

char ch = 'a';

a.add(6, ch); // заменить 6 на >=8 – ошибка выполнения

System.out.println(a);

ListIterator<Character> it;// параметризация обязательна

it= a.listIterator(2);// извлечение итератора списка в позицию

System.out.println("добавление элемента в позицию "

+ it.nextIndex());

it.add('X');// добавление элемента без замены в позицию итератора

System.out.println(a);

// сравнить методы

int index = a.lastIndexOf(ch); // a.indexOf(ch);

a.set(index, 'W'); // замена элемента без итератора

System.out.println(a + "после замены элемента");

if (a.contains(ch)) {

a.remove(a.indexOf(ch));

}

System.out.println(a + "удален элемент " + ch);

}

}

В результате будет выведено:

коллекция пуста: true

[a, b, c, d, e, f, a, g]

Наши рекомендации