Рубрики
Без рубрики

Руководство по группировке Java 8Ва коллектор

Руководство по Java 8 группировкаСовего коллекционера с примерами использования.

Автор оригинала: baeldung.

1. Введение

В этом учебнике Посмотрим, как группировка коллектор работает на различных примерах.

Для того, чтобы понять материал, охватываемый в этом учебнике, нам понадобится базовое знание функций Java 8. Мы можем взглянуть на введение в Java 8 Streams и руководство для Java 8 в коллекционеров для этих основ.

Дальнейшее чтение:

Соберите Java Stream в неизменяемую коллекцию

Java 8 Коллекционеры ToMap

2. группировкаКоллекторы

Java 8 Поток API позволяет обрабатывать сбор данных декларативно.

Статические методы завода Коллекционеры.группировкаБев() и Коллекционеры.группировкаБиКонкурент () предоставить нам функциональность, аналогичную ‘ ГРУППА ПО’ пункт на языке S’L. Мы используем их для группировки объектов по свойству и хранения результатов в Карта пример.

Перегруженные методы группировка ар:

  • Во-первых, с функцией классификации в качестве параметра метода:

static  Collector>> 
  groupingBy(Function classifier)
  • Во-вторых, с функцией классификации и вторым коллектором в качестве параметров метода:

static  Collector>
  groupingBy(Function classifier, 
    Collector downstream)
  • Наконец, с функцией классификации метод поставщика (который обеспечивает Карта реализация, которая содержит конечный результат), и второй коллектор в качестве параметров метода:

static > Collector
  groupingBy(Function classifier, 
    Supplier mapFactory, Collector downstream)

2.1. Пример настройки кода

Чтобы продемонстрировать использование группировкаБай () , давайте определим БлогПост класса (мы будем использовать поток БлогПост объекты):

class BlogPost {
    String title;
    String author;
    BlogPostType type;
    int likes;
}

Далее, BlogPostType :

enum BlogPostType {
    NEWS,
    REVIEW,
    GUIDE
}

Затем Список БлогПост Объектов:

List posts = Arrays.asList( ... );

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

class Tuple {
    BlogPostType type;
    String author;
}

2.2. Простая группировка по одной колонне

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

Чтобы сгруппить сообщения в блоге список их тип :

Map> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType));

2.3. группировкав соответствии со сложным типом ключа карты

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

Чтобы сгруппить сообщения в блоге в списке по тип и автор объединены в Тупл пример:

Map> postsPerTypeAndAuthor = posts.stream()
  .collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));

2.4. Изменение типа значения возвращенной карты

Вторая перегрузка группировка берет дополнительный второй коллектор (вниз по течению коллектор), который применяется к результатам первого коллектора.

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

Давайте использовать toSet () коллектор, как вниз по течению коллектора и получить Установить сообщений в блоге (вместо Список ):

Map> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, toSet()));

2.5. Группировка по нескольким полям

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

Сгруппить Список БлогПост s первый по автор а затем тип :

Map> map = posts.stream()
  .collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));

2.6. Получение среднего от групповых результатов

Используя коллектор ниже по течению, мы можем применить функции агрегации в результатах функции классификации.

Например, чтобы найти среднее количество любит для каждого блога тип :

Map averageLikesPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));

2.7. Получение суммы от групповых результатов

Подсчитать общую сумму любит для каждого тип :

Map likesPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));

2.8. Получение максимума или минимума от групповых результатов

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

Map> maxLikesPerPostType = posts.stream()
  .collect(groupingBy(BlogPost::getType,
  maxBy(comparingInt(BlogPost::getLikes))));

Аналогичным образом, мы можем применить minBy вниз по течению коллектор, чтобы получить сообщение в блоге с минимальным количеством любит .

Обратите внимание, что maxBy и minBy коллекторы учитывают возможность того, что коллекция, к которой они применяются, может быть пустой. Вот почему тип значения на карте является Необязательно .

2.9. Получение резюме атрибута сгруппированных результатов

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

Давайте вычислим резюме для атрибута отметки «Нравится» в блогах для каждого типа:

Map likeStatisticsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  summarizingInt(BlogPost::getLikes)));

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

2.10. Сопоставление групповых результатов с другим типом

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

Давайте сотрясаем титульный s сообщений для каждого блога тип :

Map postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]"))));

То, что мы сделали здесь, чтобы сопоставить каждый БлогПост экземпляр к своему титульный а затем уменьшить поток названий должностей до конкатенатированного Струнные . В этом примере тип Карта значение также отличается от значения Список тип.

2.11. Изменение типа карты возврата

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

Давайте возьмем EnumMap путем прохождения EnumMap функции поставщика для группировка метод:

EnumMap> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  () -> new EnumMap<>(BlogPostType.class), toList()));

3. Параллельная группировкаБи коллекционер

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

Для одновременной операции группировки поток должен быть параллельным:

ConcurrentMap> postsPerType = posts.parallelStream()
  .collect(groupingByConcurrent(BlogPost::getType));

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

4. Java 9 Дополнения

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

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

В этой статье мы изучили использование группировка коллектор, предлагаемый Java 8 Коллекционеры API.

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

Полную реализацию примеров в этой статье можно найти в проект GitHub .