Статьи

Группировка, преобразование и сокращение с помощью Java 8

1. Введение

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

В этом посте мы узнаем, как применять преобразования и сокращения к результату группировки.

  • Здесь вы можете просмотреть исходный код следующих примеров.

2. Группировка и преобразование

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

Теперь мы хотим знать, какие домашние животные принадлежат людям, живущим в Нью-Йорке. Мы просим домашних животных, поэтому мы не можем просто сделать группировку, так как мы возвращаем коллекцию людей. Нам нужно сгруппировать людей по городам, а затем преобразовать поток в коллекцию домашних животных.

Для этого мы используем отображение результатов группы следующим образом:

01
02
03
04
05
06
07
08
09
10
public void groupAndTransform(List<Person> persons) {
    final Map<String, List<Pet>> petsGroupedByCity = persons.stream().collect(
        groupingBy(
            Person::getCity,
            mapping(Person::getPet, toList())
        )
    );
     
    System.out.println("Pets living in New York: " + petsGroupedByCity.get("NYC"));
}

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

3. Группировка, преобразование и сокращение

Предыдущий пример полезен для преобразования групп объектов, но, возможно, мы не хотим получать полный список для каждой группы. В этом примере мы по-прежнему хотим группировать домашних животных по городам их владельцев, но на этот раз мы хотим получить только самых старых домашних животных из каждого списка.

Метод collectionAndThen от Collectors позволяет нам сделать окончательное преобразование в результат группировки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
public void groupTransformAndReduce(List<Person> persons) {
    final Map<String, Pet> olderPetOfEachCity = persons.stream().collect(
        groupingBy(
            Person::getCity,
            collectOlderPet()
        )
    );
     
    System.out.println("The older pet living in New York is: " + olderPetOfEachCity.get("NYC"));
}
 
private Collector<Person, ?, Pet> collectOlderPet() {
    return collectingAndThen(
        mapping(
            Person::getPet,
            Collectors.maxBy((pet1, pet2) -> Integer.compare(pet1.getAge(), pet2.getAge()))
        ), Optional::get);
    }

После того, как мы группируем людей по городам, собирая AndThen, мы преобразовываем каждого человека в списке каждого города в его питомца, а затем применяем сокращение, чтобы получить питомца с самым высоким возрастом в списке.

4. Вывод

API Collectors позволяет нам не только группировать коллекции вещей, но также вносить преобразования и сокращения для получения различных объектов в зависимости от наших потребностей.