Сбор элементов потока в неизменяемую коллекцию

В этом уроке мы научимся собирать элементы из потока Java в неизменяемую или немодифицируемую коллекцию.

1. Использование Collectors.collectingAndThen() – Java 8

Collectors.collectingAndThen() был представлен в Java 8 как часть изменений лямбда-выражений. Этот метод принимает два параметра: сборщик и завершающую функцию.

Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

Мы можем разбить приведенную выше функцию на два этапа:

  • Collectors.toList() соберет поток в изменяемый список.
  • Collections.unmodifiableList() преобразует изменяемый список в неизменяемый список типа java.util.Collections$UnmodifiableRandomAccessList.

Мы можем записать оба шага по отдельности следующим образом:

List<Integer> mutableList = Arrays.asList(1, 2, 3, 4, 5).stream().collect(Collectors.toList());List<Integer> unmodifiableList = Collections.unmodifiableList(mutableList);

См. также: Сбор элементов потока в список

2. Использование Collectors.toUnmodifiableList() – Java 10

Collectors.toUnmodifiableList() — это статическая функция, представленная в Java 10. Это сокращение от предыдущего решения, которое собирает поток в неизменяемый список в два этапа.

Он возвращает объект типа java.util.ImmutableCollections$ListN и выдает исключение NullPointerException, если встречает какие-либо значения null. Обратите внимание, что ImmutableCollections — это класс-контейнер для различных неизменяемых коллекций.

var unmodifiableList = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableList());

Мы можем использовать Collectors.toUnmodifiableSet(), чтобы собрать элементы потока в немодифицируемый набор.

var unmodifiableSet = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableSet());

Аналогично, мы можем использовать Collectors.toUnmodifiableMap() для сбора элементов в неизменяемую Map. Она принимает два параметра:

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

В следующем примере мы создадим карту с целыми числами из списка в качестве ключей и квадратом целого числа в качестве значения.

var unmodifiableMap = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableMap(i -> i, i -> i * i));

3. Использование Stream.toList() – Java 16

В Java 16 интерфейс Stream представил новый метод по умолчанию toList(), который возвращает неизменяемый список.

var unmodifiableList = Stream.of(1, 2, 3, 4, 5).toList();

4. Использование библиотеки Guava от Google

Поскольку Guava — внешняя библиотека, ее нужно будет добавить в classpath. Если вы используете Maven, добавьте зависимость Guava следующим образом:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version></dependency>

4.1 Использование ImmutableList.toImmutableList()

Начиная с Guava v21.0, мы можем использовать статический метод ImmutableList.toImmutableList(), который собирает элементы в неизменяемый список.

Метод ImmutableList.toImmutableList() возвращает объект типа com.google.common.collect.RegularImmutableList и выдает исключение NullPointerException, если обнаружит какие-либо значения null.

var unmodifiableList = Stream.of(1, 2, 3, 4, 5).collect(ImmutableList.toImmutableList());

4.2 Использование Collectors.collectingAndThen() с ImmutableList::copyOf

Этот подход похож на описанный выше. Здесь вместо этого мы используем ImmutableList::copyOf в качестве завершающей функции.

var unmodifiableList = Stream.of(1, 2, 3, 4, 5).collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf));

5. Неизменяемые и немодифицируемые коллекции

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

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

Мы вообще не можем изменять неизменяемые коллекции — они не являются оберткой для других коллекций — у них есть свои собственные элементы.

6. Заключение

В этом руководстве по коллекциям Java были рассмотрены различные способы преобразования потока Java в неизменяемую коллекцию. Рекомендуется использовать решение, доступное в последней версии Java, которую мы используем.

Прокрутить вверх