1. введение
Мы часто хотим преобразовать Java поток в коллекцию. Обычно это приводит к изменяемой коллекции, но мы можем настроить ее.
В этом коротком уроке мы рассмотрим различные способы сбора Java потока в неизменяемую коллекцию .
2. Зависимость Maven
Мы собираемся использовать библиотеку Google Guava для приведения некоторых из наших примеров:
com.google.guava guava 22.0
Другие наши примеры взяты из стандартной библиотеки.
3. Использование сбора Java, А Затем
Метод collectingAndThen из класса Collectors Java принимает Collector и finisher | Функцию . Этот финишер применяется к результату, возвращенному из Сборщика:
ListgivenList = Arrays.asList("a", "b", "c"); List result = givenList.stream() .collect(collectingAndThen(toList(), ImmutableList::copyOf)); System.out.println(result.getClass());
При таком подходе, поскольку мы не можем использовать для сбора коллектора напрямую, нам нужно собрать элементы во временный список. Затем мы строим из него неизменяемый список.
Поэтому в этом примере мы преобразуем Stream в List с помощью сборщика ToList , а затем создаем ImmutableList . ImmutableList является частью библиотеки Guava.
Кроме того, если мы запишем выходные данные в консоль, мы получим класс базовой реализации List :
class com.google.common.collect.RegularImmutableList
4. Использование коллекторов Гуавы
Начиная с Guava 21, каждый неизменяемый класс поставляется с сопровождающим Collector , который так же прост в использовании, как и стандартный Collector s Java:
Listlist = IntStream.range(0, 9) .boxed() .collect(ImmutableList.toImmutableList());
Результирующим экземпляром является RegularImmutableList :
class com.google.common.collect.RegularImmutableList
5. Создание пользовательского коллектора
У нас также есть возможность реализовать пользовательский коллектор .
5.1. Базовый Неизменяемый Коллектор
Для достижения этой цели мы можем использовать метод static Collector.of :
public staticCollector , List > toImmutableList() { return Collector.of(ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableList); }
Мы можем использовать эту функцию так же, как и любой встроенный Коллектор :
ListgivenList = Arrays.asList("a", "b", "c", "d"); List result = givenList.stream() .collect(MyImmutableListCollector.toImmutableList());
Наконец, давайте проверим тип вывода:
class java.util.Collections$UnmodifiableRandomAccessList
5.2. Сделать коллектор My ImmutableList универсальным
Наша реализация имеет одно ограничение – она всегда возвращает неизменяемый экземпляр, поддерживаемый ArrayList . Однако с небольшим улучшением мы можем заставить этот коллектор возвращать указанный пользователем тип:
public static> Collector > toImmutableList( Supplier supplier) { return Collector.of( supplier, List::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableList); }
Поэтому теперь вместо определения Поставщика в реализации метода мы запрашиваем Поставщика у пользователя:
ListgivenList = Arrays.asList("a", "b", "c", "d"); List result = givenList.stream() .collect(MyImmutableListCollector.toImmutableList(LinkedList::new));
Кроме того, мы используем Связанный список вместо ArrayList .
class java.util.Collections$UnmodifiableList
На этот раз мы получили unmodifiableList вместо UnmodifiableRandomAccessList .
6. Использование Java в немодифицируемом списке
Начиная с Java 10, мы можем использовать их для unmodifiableList метод из класса Java Collectors :
ListgivenList = Arrays.asList("a", "b", "c"); List result = givenList.stream() .collect(toUnmodifiableList());
Используя этот метод, мы получаем реализацию List , которая не поддерживает null значения из неизменяемых коллекций Java :
class java.util.ImmutableCollections$ListN
7. Заключение
В этой короткой статье мы рассмотрели различные способы сбора Потока в неизменяемую Коллекцию .
Как всегда, полный исходный код этой статьи находится на GitHub. Они разделены по версии Java на примеры для разделов 2-5 и раздела 6 .