Java stream groupingby sort

Окончательное руководство по Java Stream API groupingBy () Collector

GroupingBy () является одним из самых мощных и настраиваемых потока API коллекторов.

Если вы постоянно обнаруживаете, что не выходите за рамки следующего использования groupingBy() :

Или, если вы просто хотели обнаружить его потенциальное использование, то эта статья для вас!

обзор

Проще говоря, groupingBy () предоставляет функциональность, аналогичную предложению SQL GROUP BY, только для API Java Stream .

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

Например, если мы хотим , чтобы группы строк по их длине, мы могли бы сделать , что, переходя String::length к groupingBy() :

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length));  System.out.println(result); //

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

Группировка в реализацию пользовательской карты

Если вам нужно предоставить пользовательскую Map реализацию, вы можете сделать это, используя предоставленную groupingBy() перегрузку:

List strings = List.of("a", "bb", "cc", "ddd");  TreeMap result = strings.stream() .collect(groupingBy(String::length, TreeMap::new, toList()));  System.out.println(result); //

Предоставление пользовательской нисходящей коллекции

Если вам нужно хранить сгруппированные элементы в пользовательской коллекции, это можно сделать с помощью toCollection() сборщика.

Например, если вы хотите сгруппировать элементы в TreeSet экземплярах, это может быть так просто:

groupingBy(String::length, toCollection(TreeSet::new))

И вот, у нас есть полный пример:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, toCollection(TreeSet::new)));  System.out.println(result); //

Группировка и подсчет предметов в группах

Если вы просто хотите узнать количество сгруппированных элементов, это может быть так же просто, как и предоставить собственный counting() сборщик:

groupingBy(String::length, counting())
List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, counting()));  System.out.println(result); //

Группировка и объединение элементов в виде строк

Если вам нужно сгруппировать элементы и создать одно строковое представление каждой группы, это можно сделать с помощью joining() сборщика:

groupingBy(String::length, joining(",", "[", "]"))

И, чтобы увидеть это в действии, посмотрите следующий пример:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, joining(",", "[", "]")));  System.out.println(result); //

Группировка и фильтрация товаров

Иногда может возникнуть необходимость исключить некоторые элементы из сгруппированных результатов. Это может быть достигнуто с помощью filtering() коллектора:

groupingBy(String::length, filtering(s -> !s.contains("c"), toList()))

Вот этот коллекционер в действии:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, filtering(s -> !s.contains("c"), toList())));  System.out.println(result); //

Группировка и расчет среднего по группе

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

Вот эти коллекционеры в действии:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, averagingInt(String::hashCode)));  System.out.println(result); //

Отказ от ответственности: String::hashCode был использован в качестве заполнителя.

Группировка и расчет суммы на группу

Если вы хотите получить сумму из свойств сгруппированных элементов, для этого также есть несколько вариантов:

Вот эти коллекционеры в действии:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, summingInt(String::hashCode)));  System.out.println(result); //

Отказ от ответственности: String::hashCode был использован в качестве заполнителя.

Группировка и расчет статистической сводки по группе

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

Вот вышеупомянутые коллекционеры в действии:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, summarizingInt(String::hashCode)));  System.out.println(result); 

Давайте посмотрим на результат (удобный переформатированный):

 1=IntSummaryStatistics count=1, sum=97, min=97, average=97.000000, max=97>, 2=IntSummaryStatistics count=2, sum=6304, min=3136, average=3152.000000, max=3168>, 3=IntSummaryStatistics count=1, sum=99300, min=99300, average=99300.000000, max=99300> >

Отказ от ответственности: String::hashCode был использован в качестве заполнителя.

Группировка и сокращение элементов

Если вы хотите выполнить операцию сокращения для сгруппированных элементов, вы можете использовать reducing() коллектор:

groupingBy(List::size, reducing(List.of(), (l1, l2) -> . )))

Вот пример reducing() коллектора:

List strings = List.of("a", "bb", "cc", "ddd");  Map> result = strings.stream() .map(toStringList()) .collect(groupingBy(List::size, reducing(List.of(), (l1, l2) -> Stream.concat(l1.stream(), l2.stream()) .collect(Collectors.toList()))));  System.out.println(result); //

Группировка и расчет Max / Min Item

Если вы хотите извлечь элемент max / min из группы, вы можете просто использовать max() / min() collector:

groupingBy(String::length, Collectors.maxBy(Comparator.comparing(String::toUpperCase)))

Вот эти коллекционеры в действии:

List strings = List.of("a", "bb", "cc", "ddd");  Map result = strings.stream() .collect(groupingBy(String::length, Collectors.maxBy(Comparator.comparing(String::toUpperCase))));  System.out.println(result); //

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

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

Составление нижестоящих коллекторов

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

Пример № 1

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

Мы можем сделать это довольно легко:

var result = strings.stream() .collect( groupingBy(String::length, mapping(String::toUpperCase, filtering(s -> s.length() > 1, toCollection(TreeSet::new)))));  //result 

Пример № 2

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

Мы можем достичь этого также:

var result = strings.stream() .collect( groupingBy(String::length, mapping(toStringList(), flatMapping(s -> s.stream().distinct(), filtering(s -> s.length() > 0, mapping(String::toUpperCase, reducing("", (s, s2) -> s + s2))))) ));  //result 

источники

Все приведенные выше примеры можно найти в моем проекте GitHub.

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

Источник

Читайте также:  Прогнозирование временных рядов python sarima
Оцените статью