В любом контейнерном классе должны присутствовать методы для помещения объектов в него и извлечения этих объектов. В конце концов, это основная задача коллекций — хранение различных объектов. В Vector
, addElement()
является методом для добавления объектов, а elementAt()
— единственным способом получения объектов. Vector
очень гибкий, позволяющий выбирать любой объект в любое время и использовать различные индексы для выбора нескольких элементов.
Если взглянуть на эту проблему с более высокого уровня, можно заметить один недостаток: требуется знать точный тип коллекции заранее, что делает использование других типов невозможным. На первый взгляд, это может показаться незначительной проблемой. Однако если вы начали использовать Vector
, а затем решили изменить его на List
(часть Java 1.2 Collections API) по причинам производительности, как бы вы могли это сделать?Для решения этой проблемы можно использовать концепцию итератора (Iterator
). Это может быть объект, который проходит через последовательность объектов, выбирает каждый объект из этой последовательности, при этом клиентский программист не знает или не заботится о базовой структуре этой последовательности. Кроме того, мы обычно считаем итератор легковесным объектом; другими словами, создание такого объекта требует минимальных затрат. Именно поэтому часто встречаются странные ограничения на работу итератора. Например, некоторые итераторы могут перемещаться только в одном направлении.
Примером итератора с такими ограничениями является перечисление (Enumeration
) в Java. Он может использоваться только для следующих действий:(1) Используйте метод elements()
, чтобы запросить коллекцию, которая предоставляет вам Enumeration
. При первом вызове метода nextElement()
, этот Enumeration
вернёт первый элемент последовательности.
(2) Используйте nextElement()
для получения следующего объекта.
(3) Используйте hasMoreElements()
для проверки наличия ещё объектов в последовательности.
②: Слово "итератор" часто встречается в C++ и других областях ООП, поэтому трудно понять, почему разработчики Java выбрали такое странное название. Java 1.2 Collections API исправила эту и многие другие проблемы.
Использовать Enumeration
можно только для выполнения вышеописанных действий, больше ничего. Это простая реализация итератора, но она всё равно весьма мощна. Чтобы лучше понять её работу, давайте рассмотрим пример программы CatsAndDogs.java
, упомянутый ранее в этой главе. В исходной версии используется метод elementAt()
для выбора каждого элемента, однако в модифицированной версии видно использование "перечисления":
//: CatsAndDogs2.java
// Простая коллекция с перечнем (enumeration)
import java.util.*;
class Cat2 {
private int catNumber;
Cat2(int i) {
catNumber = i;
}
void print() {
System.out.println("Номер кошки " + catNumber);
}
}
class Dog2 {
private int dogNumber;
Dog2(int i) {
dogNumber = i;
}
void print() {
System.out.println("Номер собаки " + dogNumber);
}
}
``````java
public class CatsAndDogs2 {
public static void main(String[] args) {
Vector cats = new Vector();
for (int i = 0; i < 7; i++)
cats.addElement(new Cat2(i));
// Нет проблем добавить собаку в список кошек:
cats.addElement(new Dog2(7));
Enumeration e = cats.elements();
while (e.hasMoreElements())
((Cat2) e.nextElement()).print();
// Собака обнаруживается только во время выполнения программы
}
}
///:~
```Мы видим, что единственное изменение заключается в последних нескольких строках. Теперь вместо:
```java
for(int i = 0; i < cats.size(); i++)
((Cat)cats.elementAt(i)).print();
используется перечень (Enumeration
) для прохождения по всему списку:
while(e.hasMoreElements())
((Cat2)e.nextElement()).print();
Используя Enumeration
, нам нет необходимости знать количество элементов в коллекции. Все необходимые действия выполняются автоматически методами hasMoreElements()
и nextElement()
.
Далее рассмотрим ещё один пример, создадим универсальный метод печати:
//: HamsterMaze.java
// Использование перечня (enumeration)
import java.util.*;
class Hamster {
private int hamsterNumber;
Hamster(int i) {
hamsterNumber = i;
}
public String toString() {
return "Это хомяк номер #" + hamsterNumber;
}
}
class Printer {
static void printAll(Enumeration e) {
while(e.hasMoreElements())
System.out.println(
e.nextElement().toString());
}
}
public class HamsterMaze {
public static void main(String[] args) {
Vector v = new Vector();
for(int i = 0; i < 3; i++)
v.addElement(new Hamster(i));
Printer.printAll(v.elements());
}
} ///:~
Посмотрим внимательнее на метод печати:
static void printAll(Enumeration e) {
while(e.hasMoreElements())
System.out.println(
e.nextElement().toString());
}
```Обратите внимание, что здесь отсутствуют данные о типе коллекции. У нас есть только `Перечисление` (Enumeration). Для получения информации о коллекции достаточно иметь `Перечисление`: можно получить следующий объект и узнать, достигнут ли конец списка. Получение серии объектов и их последующее перебирание для выполнения конкретной операции — это ценная идея программирования, которую мы будем использовать в различных местах этой книги.
Этот пример даже более универсален, так как он использует обычный метод toString()
, который является частью класса Object
. Вот ещё один способ вызова вывода (хотя это может быть менее эффективным):
System.out.println("" + e.nextElement());
```
Он использует встроенную в Java "автоматическую строковую конвертацию". Когда компилятор встречает строку, за которой следует оператор `+`, он ожидает следующей строки и автоматически вызывает `toString()`. В Java 1.1 первая строка была необязательной; все объекты преобразуются в строки. Это также можно сделать с одним преобразованием, чтобы получить тот же эффект, что при вызове `toString()`:
```markdown
System.out.println((String) e.nextElement())
```
Но обычно мы хотим делать больше, чем просто вызывать методы `Object`, поэтому снова сталкиваемся с проблемой приведения типов. Для интересующего нас типа мы должны предположить, что у нас есть перечисление (`Enumeration`), а затем преобразовать результат в нужный тип (если произойдет ошибка, будет выброшено исключение времени выполнения).
```
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )