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

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

Жанры

Философия Java3

Эккель Брюс

Шрифт:

//: holding/Envi ronmentVariables.java import java util *;

public class EnvironmentVariables {

public static void main(String[] args) {

for (Map Entry entry System getenvO .entrySetO) { System.out.println(entry.getKey + ": " + entry. getValueO);

}

}

} /* (Выполните, чтобы увидеть результат) *///:-

System.getenv возвращает Map, entrySet создает Set с элементами Map.Entry, a Set поддерживает Iterable и поэтому может использоваться в цикле foreach.

Синтаксис foreach работает с массивами и всем, что поддерживает Iterable, но это не означает, что массив автоматически поддерживает Iterable:

// hoiding/ArraylsNotIterable.java import java.util.*;

public class ArraylsNotlterable {

static <T> void test(Iterable<T> ib) { for(T t • ib)

System.out.print(t + " ");

}

public static void main(String[] args) { test(Arrays.asList(l. 2, 3)); StringC] strings = { "А", "В". "С" }: // Массив работает в foreach, но не является Iterable: //! test(strings);

// его необходимо явно преобразовать к Iterable: testCArrays.asLi st(stri ngs));

}

} /* Output: 1 2 3 А В С *///•-

Попытка передачи массива в аргументе Iterable завершается неудачей. Автоматическое преобразование в Iterable не производится; его необходимо выполнять вручную.

Идиома «метод-адаптер»

Что делать, если у вас имеется существующий класс, реализующий Iterable, и вы хотите добавить новые способы использования этого класса в синтаксисе foreach? Допустим, вы хотите иметь возможность выбора между перебором списка слов в прямом или обратном направлении. Если просто воспользоваться наследованием от класса и переопределить метод iterator, то существующий метод будет заменен и никакого выбора не будет.

Одно из решений этой проблемы основано на использовании идиомы, которую я называю «методом-адаптером». Термин «адаптер» происходит от одноименного паттерна: вы должны предоставить интерфейс, необходимый для работы синтаксиса foreach. Если у вас имеется один интерфейс, а нужен другой, проблема решается написанием адаптера. В данном случае требуется добавить к стандартному «прямому» итератору обратный, так что переопределение исключено. Вместо этого мы добавим метод, создающий объект Iterable, который может использоваться в синтаксисе foreach. Как будет показано далее, это позволит нам предоставить несколько вариантов использования foreach:

//: hoiding/AdapterMethodldiom.java

// Идиома "метод-адаптер" позволяет использовать foreach

// с дополнительными разновидностями Iterable.

import java.util.*;

class ReversibleArrayList<T> extends ArrayList<T> {

public ReversibleArrayList(Collection<T> c) { super(c); }. public Iterable<T> reversedO {

return new Iterable<T> {

public Iterator<T> iteratorO {

return new Iterator<T> {

int current = sizeO - 1,

public boolean hasNextO { return current > -1;

}

public T nextO { return get (current--); } public void removeO { // He реализован throw new

UnsupportedOperationExceptionO;

}

} •

}

}:

}

}

public class AdapterMethodldiom {

public static void main(String[] args) { ReversibleArrayList<String> ral =

new ReversibleArrayList<String>(

Arrays.asList(To be or not to be".splitC' "))): // Получаем обычный итератор, полученный при помощи iteratorO: forCString s : ral)

System.out.print(s + " "); System.out printlnO;

// Передаем выбранный нами Iterable forCString s • ral .reversedO)

System.out.print(s + " "),

}

} /* Output To be or not to be be to not or be To */// ~

Если просто поместить объект ral в синтаксис foreach, мы получим (стандартный) «прямой» итератор. Но если вызвать для объекта reversed, поведение изменится.

Использовав этот прием, можно добавить в пример IterableClass.java два метода-адаптера:

// hoidi ng/MultiIterableClass.java // Adding several Adapter Methods, import java util *;

public class MultilterableClass extends IterableClass { public Iterable<String> reversedO {

return new Iterable<String> {

public Iterator<String> iteratorO {

return new Iterator<String> {

int current = words length - 1,

public boolean hasNextO { return current > -1;

}

public String nextO { return words[current--];

}

public void removeО { // He реализован throw new

UnsupportedOperationException,

}

}:

}

}.

}

public Iterable<String> randomizedO { return new Iterable<String> {

public Iterator<String> iteratorO { List<String> shuffled =

new ArrayList<String>(Arrays.asList(words)); Collections.shuffleCshuffled, new Random(47)); return shuffled.iterator;

}

}:

}

public static void main(String[] args) {

MultilterableClass mic = new MultiIterableClassO; for (String s : mic. reversedO)

System out print(s + " "): System, out. pri ntlnO. for(String s : mic.randomizedO)

System out.print(s + " "); System.out.prmtlnO: продолжение & for(String s : mic)

System.out.print(s + " ");

}

} /* Output:

banana-shaped, be to Earth the know we how is that And is banana-shaped. Earth that how the be And we know to And that is how we know the Earth to be banana-shaped *///:-

Из выходных данных видно, что метод Collections.shuffle не изменяет исходный массив, а только переставляет ссылки в shuffled. Так происходит только потому, что метод randomized создает для результата Arrays.asList «обертку» в виде ArrayList. Если бы операция выполнялась непосредственно с объектом List, полученным от Arrays.asList, то это привело бы к изменению нижележащего массива:

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

Царь царей

Билик Дмитрий Александрович
9. Бедовый
Фантастика:
фэнтези
мистика
5.00
рейтинг книги
Царь царей

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

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

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9

Точка Бифуркации VI

Смит Дейлор
6. ТБ
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Точка Бифуркации VI

Барон не играет по правилам

Ренгач Евгений
1. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон не играет по правилам

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Лекарь Империи 9

Карелин Сергей Витальевич
9. Лекарь Империи
Фантастика:
городское фэнтези
аниме
боевая фантастика
5.00
рейтинг книги
Лекарь Империи 9

Цикл "Идеальный мир для Лекаря". Компиляция. Книги 1-30

Сапфир Олег
Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Цикл Идеальный мир для Лекаря. Компиляция. Книги 1-30

Рассвет русского царства

Грехов Тимофей
1. Новая Русь
Документальная литература:
историческая литература
5.00
рейтинг книги
Рассвет русского царства

Первый среди равных. Книга VIII

Бор Жорж
8. Первый среди Равных
Фантастика:
аниме
фантастика: прочее
эпическая фантастика
попаданцы
5.00
рейтинг книги
Первый среди равных. Книга VIII

Отморозок 5

Поповский Андрей Владимирович
5. Отморозок
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Отморозок 5

Император Пограничья 4

Астахов Евгений Евгеньевич
4. Император Пограничья
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 4

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

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

Отморозок 4

Поповский Андрей Владимирович
4. Отморозок
Фантастика:
попаданцы
фантастика: прочее
5.00
рейтинг книги
Отморозок 4