Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

В строках 7 и 8 из List успешно удаляется заданный объект. Строка 9 и предшествующий ей код демонстрируют вставку элемента в середину списка. Метод subList позволяет легко создать «срез» из подмножества элементов списка; естественно, при передаче его методу containsAll большего списка будет получен истинный результат. Вызовы Collections.sort и Collec-tions.shuffle для sub не влияют на результат вызова containsAll.

Метод retainAll фактически выполняет операцию «пересечения множеств», то есть определения всех элементов сору, которые также присутствуют в sub. И снова поведение метода зависит от реализации equals.

В строке 14 представлен результат удаления элемента по индексу — это проще, чем удаление по ссылке на объект, потому что вам не придется беспокоиться о поведении equals.

Работа метода removeAll также зависит от equals. Как подсказывает название, метод удаляет из List все объекты, входящие в List-аргумент.

Название метода set выбрано неудачно, потому что оно совпадает с именем класса Set — возможно, лучше было бы назвать метод «replace», потому что он заменяет элемент с заданным индексом (первый аргумент) вторым аргументом.

В строке вывода 17 показано, что для List существует перегруженный метод addAll, вставляющий новый список в середину исходного списка (вместо простого добавления в конец методом addAll, унаследованным от Collection).

В строках 18-20 представлен результат вызова методов isEmpty и clear. Строки 22 и 23 демонстрируют, что любой объект Collection можно преобразовать в массив с использованием to Array .

Итераторы

У любого контейнера должен существовать механизм вставки и выборки элементов. В конце концов, контейнер предназначен именно для хранения объектов. При работе с List для вставки может использоваться метод add, а для выборки — метод get (впрочем, существуют и другие способы).

Если взглянуть на ситуацию с более высокого уровня, обнаруживается проблема: чтобы использовать контейнер в программе, необходимо знать его точный тип. Что, если вы начали использовать в программе контейнер List, а затем обнаружили, что в вашем случае будет удобнее применить тот же код к множеству (Set)? Или если вы хотите написать универсальный код, который не зависит от типа контейнера и может применяться к любому контейнеру?

С данной абстракцией хорошо согласуется концепция итератора (iterator). Итератор — это объект, обеспечивающий перемещение по последовательности объектов с выбором каждого объекта этой последовательности, при этом программисту-клиенту не надо знать или заботиться о лежащей в ее основе структуре. Вдобавок, итератор обычно является так называемым «легковесным» (lightweight) объектом: его создание должно обходиться без заметных затрат ресурсов. Из-за этого итераторы часто имеют ограничения; например, Iterator в Java поддерживает перемещение только в одном направлении. Его возможности не так уж широки, но с его помощью можно сделать следующее:

• Запросить у контейнера итератор вызовом метода iterator. Полученный итератор готов вернуть начальный элемент последовательности при первом вызове своего метода next.

• Получить следующий элемент последовательности вызовом метода next.

• Проверить, остались ли еще объекты в последовательности (метод hasNext).

• Удалить из последовательности последний элемент, возвращенный итератором, методом remove.

Чтобы увидеть итератор в действии, мы снова воспользуемся иерархией Pets:

// holding/Simplelteration java import typeinfo pets *; import java util *.

public class Simplelteration {

public static void main(String[] args) {

List<Pet> pets = Pets arrayList(12); Iterator<Pet> it = pets iteratorO. whi 1 e(it hasNextO) {

Pet p = it nextO;

System.out pri nt(p id + " " + p + " ");

}

System.out printlnO; // Более простой способ, for(Pet p • pets)

System out print(p id + "+ p + " "); System, out. printlnO;

// Итератор также способен удалять элементы: it = pets. iteratorO. for(int i = 0: i < 6: i++) { it nextO: it.removeO.

}

System.out.pnntln(pets):

}

} /* Output-

0:Rat l:Manx 2:Cymric 3-Mutt 4-Pug 5:Cymric 6.Pug 7:Manx 8.Cymric 9:Rat 10:EgyptianMau 11.Hamster

0-Rat 1-Manx 2-Cymric 3:Mutt 4:Pug 5.Cymric 6:Pug 7:Manx 8:Cymric 9-Rat 10-EgyptianMau 11:Hamster

[Pug. Manx. Cymric. Rat. EgyptianMau. Hamster] *///•-

Мы видим, что с Iterator можно не беспокоиться о количестве элементов в последовательности. Проверка осуществляется методами hasNext и next.

Если вы просто перебираете элементы списка в одном направлении, не пытаясь модифицировать его содержимое, «синтаксис foreach» обеспечивает более компактную запись.

Iterator удаляет последний элемент, полученный при помощи next, поэтому перед вызовом remove необходимо вызвать next.

Теперь рассмотрим задачу создания метода display, не зависящего от типа контейнера:

//: hoiding/CrossContaiпегIteration.java import typeinfo.pets.*, import java.util *;

public class CrossContainerlteration {

public static void display(Iterator<Pet> it) { while(it.hasNextO) {

Pet p = it nextO:

System.out.print(p.id + ":" + p + " ");

}

System out.printlnO;

}

public static void main(String[] args) { продолжение &

ArrayList<Pet> pets = Pets.arrayList(8); LinkedList<Pet> petsLL = new LinkedList<Pet>(pets); HashSet<Pet> petsHS = new HashSet<Pet>(pets); TreeSet<Pet> petsTS = new TreeSet<Pet>(pets); di splay(pets.iterator); display(petsLL iteratorO); di splay(petsHS.iterator); di spl ay(petsTS. iteratorO);

}

} /* Output:

0:Rat 1-Manx 2-Cymric 3-Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 0:Rat l.Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 4:Pug 6:Pug 3:Mutt l:Manx 5:Cymric 7:Manx 2:Cymric 0:Rat 5 Cymric 2:Cymric 7:Manx l:Manx 3:Mutt 6:Pug 4:Pug 0:Rat *///:-

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

Поделиться:
Популярные книги

Как я строил магическую империю 4

Зубов Константин
4. Как я строил магическую империю
Фантастика:
боевая фантастика
постапокалипсис
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 4

Убивать чтобы жить 7

Бор Жорж
7. УЧЖ
Фантастика:
героическая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 7

Новик

Ланцов Михаил Алексеевич
2. Помещик
Фантастика:
альтернативная история
6.67
рейтинг книги
Новик

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Адепт. Том 1. Обучение

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
9.27
рейтинг книги
Адепт. Том 1. Обучение

Уарда

Эберс Георг Мориц
Проза:
историческая проза
8.00
рейтинг книги
Уарда

Я все еще не царь. Книга XXVI

Дрейк Сириус
26. Дорогой барон!
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Я все еще не царь. Книга XXVI

Черный маг императора 3

Герда Александр
3. Черный маг императора
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора 3

Черный Маг Императора 12

Герда Александр
12. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 12

Дважды одаренный. Том V

Тарс Элиан
5. Дважды одаренный
Фантастика:
аниме
альтернативная история
городское фэнтези
5.00
рейтинг книги
Дважды одаренный. Том V

На границе империй. Том 10. Часть 6

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 6

Законы Рода. Том 4

Мельник Андрей
4. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 4

Сфирот

Прокофьев Роман Юрьевич
8. Стеллар
Фантастика:
боевая фантастика
рпг
6.92
рейтинг книги
Сфирот

Лекарь

Назимов Константин Геннадьевич
2. Травник
Фантастика:
фэнтези
5.25
рейтинг книги
Лекарь