Вопрос с собеседования · Java

Как одним коллектором получить «количество элементов в каждой группе»?

MiddleЛямбды и Stream API
Коротко

groupingBy(classifier, counting()) — downstream-коллектор counting сворачивает каждую группу в число (Long).

  • Другие downstream: summingInt, averagingDouble, mapping, maxBy, toSet
  • Вложенная группировка: groupingBy(a, groupingBy(b))
  • partitioningBy — разбиение на две группы по условию

А ещё counting возвращает Long; нужен Integer — collectingAndThen или summingInt(e -> 1)

Подробно

Сила groupingBy во втором аргументе — downstream-коллекторе, который сворачивает каждую группу дальше: counting() (размер), mapping/summingInt/averagingInt (агрегаты), maxBy/minBy. Так одной строкой получают «сотрудников по отделам» (counting) или «среднюю зарплату по отделам» — вложенная свёртка вместо ручного цикла.

Пример

Map<Dept, Long> count = emps.stream()
    .collect(groupingBy(Emp::dept, counting()));
Map<Dept, Double> avgSalary = emps.stream()
    .collect(groupingBy(Emp::dept, averagingInt(Emp::salary)));

Что хотят услышать

  • groupingBy с counting.
  • Идея downstream-коллекторов.

Частые ошибки

  • Искать несуществующий size() в toMap.
  • Считать, что groupingBy умеет только Map<K,List<V>>.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗toMap(classifier, list -> list.size())
  • ✗partitioningBy(classifier, counting())
  • ✓groupingBy(classifier, counting())
  • ✗reduce(0, (a,b) -> a+1) по всему стриму

Что спросят дальше

  • Какие ещё downstream-коллекторы есть?
  • Чем partitioningBy отличается от groupingBy?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

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

Разбор собеседования