«1. Введение

Эта статья является первой в серии о новых функциях, появившихся в Версии 21 библиотеки Google Guava. Мы обсудим недавно добавленные классы и некоторые важные изменения по сравнению с предыдущими версиями Guava.

Более конкретно, мы обсудим дополнения и изменения в пакете common.collect.

В Guava 21 добавлены некоторые новые и полезные функции в пакете common.collect; давайте кратко рассмотрим некоторые из этих новых утилит и то, как мы можем извлечь из них максимальную пользу.

2. Потоки

Мы все в восторге от последнего добавления java.util.stream.Stream в Java 8. Теперь Guava хорошо использует потоки и предоставляет то, что Oracle, возможно, упустил.

Streams — это статический служебный класс с некоторыми необходимыми утилитами для обработки потоков Java 8.

2.1. Streams.stream()

Класс Streams предоставляет четыре способа создания потоков с использованием Iterable, Iterator, Optional и Collection.

Тем не менее, создание потока с использованием Collection устарело, так как оно предоставляется Java 8 из коробки:

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Stream<Integer> streamFromCollection = Streams.stream(numbers);
Stream<Integer> streamFromIterator = Streams.stream(numbers.iterator());
Stream<Integer> streamFromIterable = Streams.stream((Iterable<Integer>) numbers);
Stream<Integer> streamFromOptional = Streams.stream(Optional.of(1));

Класс Streams также предоставляет варианты с OptionalDouble, OptionalLong и OptionalInt. Эти методы возвращают поток, содержащий только этот элемент, иначе пустой поток:

LongStream streamFromOptionalLong = Streams.stream(OptionalLong.of(1));
IntStream streamFromOptionalInt = Streams.stream(OptionalInt.of(1));
DoubleStream streamFromOptionalDouble = Streams.stream(OptionalDouble.of(1.0));

2.2. Streams.concat()

Класс Streams предоставляет методы для объединения более чем одного однородного потока.

Stream<Integer> concatenatedStreams = Streams.concat(streamFromCollection, streamFromIterable,streamFromIterator);

Функциональность concat представлена ​​в нескольких вариантах: LongStream, IntStream и DoubleStream.

2.3. Streams.findLast()

Потоки имеют служебный метод для поиска последнего элемента в потоке с помощью метода findLast().

Этот метод либо возвращает последний элемент, либо Optional.empty(), если в потоке нет элементов:

List<Integer> integers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Optional<Integer> lastItem = Streams.findLast(integers.stream());

Метод findLast() работает для LongStream, IntStream и DoubleStream.

2.4. Streams.mapWithIndex()

Используя метод mapWithIndex(), каждый элемент потока несет информацию об их соответствующей позиции (индексе):

mapWithIndex( Stream.of("a", "b", "c"), (str, index) -> str + ":" + index)

Это вернет Stream.of(“a:0” ,\»b:1\»,\»c:2\»).

То же самое можно сделать с IntStream, LongStream и DoubleStream, используя перегруженную карту mapWithIndex().

2.5. Streams.zip()

Чтобы сопоставить соответствующие элементы двух потоков с помощью некоторой функции, просто используйте метод zip для Streams:

Streams.zip(
  Stream.of("candy", "chocolate", "bar"),
  Stream.of("$1", "$2","$3"),
  (arg1, arg2) -> arg1 + ":" + arg2
);

Это вернет Stream.of(“candy:$1”, «шоколад: 2 доллара», батончик: 3 доллара);

Результирующий поток будет такой же длины, как и более короткий из двух входных потоков; если один поток длиннее, его лишний элемент будет проигнорирован.

3. Компараторы

Класс Guava Ordering устарел и находится в стадии удаления в новых версиях. Большинство функций класса Ordering уже включены в JDK 8.

Guava представляет компараторы для предоставления дополнительных функций Ordering, которые еще не предоставляются стандартными библиотеками Java 8.

Давайте быстро взглянем на них.

3.1. Comparators.isInOrder()

Этот метод возвращает значение true, если каждый элемент в Iterable больше или равен предыдущему, как указано Компаратором:

List<Integer> integers = Arrays.asList(1,2,3,4,4,6,7,8,9,10);
boolean isInAscendingOrder = Comparators.isInOrder(
  integers, new AscedingOrderComparator());

3.2. Comparators.isInStrictOrder()

Очень похож на метод isInOrder(), но строго соблюдает условие, элемент не может быть равен предыдущему, он должен быть больше. Предыдущий код вернет false для этого метода.

3.3. Comparators.lexicographical()

Этот API возвращает новый экземпляр Comparator, который сортирует в лексикографическом (словарном) порядке, сравнивая соответствующие элементы попарно. Внутри он создает новый экземпляр LexicographicalOrdering\u003cS\u003e().

4. MoreCollectors

MoreCollectors содержит несколько очень полезных коллекторов, которых нет в Java 8 java.util.stream.Collectors и которые не связаны с типом com.google.common.

Давайте рассмотрим некоторые из них.

4.1. MoreCollectors.toOptional()

Здесь Collector преобразует поток, содержащий ноль или один элемент, в необязательный:

List<Integer> numbers = Arrays.asList(1);
Optional<Integer> number = numbers.stream()
  .map(e -> e * 2)
  .collect(MoreCollectors.toOptional());

Если поток содержит более одного элемента — сборщик выдаст исключение IllegalArgumentException.

4.2. MoreCollectors.onlyElement()

«С помощью этого API Collector берет поток, содержащий только один элемент, и возвращает этот элемент; если поток содержит более одного элемента, он генерирует исключение IllegalArgumentException или, если поток содержит нулевой элемент, он генерирует исключение NoSuchElementException.

5. Interners.InternerBuilder

Это внутренний класс построителя для уже существующих Interners в библиотеке Guava. Он предоставляет удобный метод для определения уровня параллелизма и типа (слабый или сильный) Interner, который вы предпочитаете:

Interners interners = Interners.newBuilder()
  .concurrencyLevel(2)
  .weak()
  .build();

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

В этой быстрой статье мы рассмотрели новые функции, добавленные в пакет common.collect. из Guava 21.

Код для этой статьи, как всегда, можно найти на Github.