← Назад к вопросам

Как сгруппировать записи таблицы по условию

2.2 Middle🔥 161 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

Группировка данных — фундаментальная операция в обработке коллекций. Рассмотрим несколько подходов от базовых до продвинутых.

1. Stream API с Collectors.groupingBy()

Самый современный и читаемый способ для Java 8+:

List<User> users = /* список пользователей */;

// Группировка по полю
Map<String, List<User>> byStatus = users.stream()
  .collect(Collectors.groupingBy(User::getStatus));
// Результат: {"active": [...], "inactive": [...], "banned": [...]}

// Группировка с кастомным условием
Map<Boolean, List<User>> byPremium = users.stream()
  .collect(Collectors.groupingBy(user -> user.getBalance() > 1000));
// Результат: {true: [premium users], false: [regular users]}

2. Группировка с дополнительной обработкой

Эхо часто нужно трансформировать значения группы:

// Подсчёт элементов в каждой группе
Map<String, Long> countByStatus = users.stream()
  .collect(Collectors.groupingBy(
    User::getStatus,
    Collectors.counting()
  ));
// Результат: {"active": 150, "inactive": 45, "banned": 5}

// Получение первого элемента в группе
Map<String, Optional<User>> firstByStatus = users.stream()
  .collect(Collectors.groupingBy(
    User::getStatus,
    Collectors.maxBy(Comparator.comparing(User::getCreatedAt))
  ));

// Суммирование значений в группе
Map<String, Integer> totalBalance = users.stream()
  .collect(Collectors.groupingBy(
    User::getStatus,
    Collectors.summingInt(User::getBalance)
  ));

3. Многоуровневая группировка

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

// Группировка по статусу, затем по регионам внутри
Map<String, Map<String, List<User>>> byStatusAndRegion = users.stream()
  .collect(Collectors.groupingBy(
    User::getStatus,
    Collectors.groupingBy(User::getRegion)
  ));
// Результат: {"active": {"Moscow": [...], "SPb": [...]}, ...}

// Сложная иерархия
Map<String, Map<Integer, List<String>>> complex = users.stream()
  .collect(Collectors.groupingBy(
    User::getStatus,
    Collectors.groupingBy(
      User::getAge,
      Collectors.mapping(
        User::getName,
        Collectors.toList()
      )
    )
  ));

4. Традиционный подход с Map (для Java 7 и ниже)

Если нельзя использовать Stream API:

Map<String, List<User>> byStatus = new HashMap<>();

for (User user : users) {
  String status = user.getStatus();
  if (!byStatus.containsKey(status)) {
    byStatus.put(status, new ArrayList<>());
  }
  byStatus.get(status).add(user);
}

5. Группировка с фильтрацией

Застройка логики группировки:

// Только активные пользователи, группировка по региону
Map<String, List<User>> activeByRegion = users.stream()
  .filter(user -> user.isActive())
  .collect(Collectors.groupingBy(User::getRegion));

// Группировка с условием в самом groupingBy
Map<String, List<User>> complex = users.stream()
  .collect(Collectors.groupingBy(
    user -> user.getAge() > 30 ? "senior" : "junior",
    Collectors.filtering(
      user -> user.getBalance() > 0,
      Collectors.toList()
    )
  ));

6. Вывод результатов

// Итерация по результатам группировки
byStatus.forEach((status, userList) -> {
  System.out.printf("Статус %s: %d пользователей\n", status, userList.size());
});

// Поиск группы с максимальным размером
String largestGroup = byStatus.entrySet().stream()
  .max(Comparator.comparingInt(e -> e.getValue().size()))
  .map(Map.Entry::getKey)
  .orElse(null);

Производительность и рекомендации

  • Stream API (groupingBy) — предпочтительный выбор для Java 8+
  • Параллельные потоки используйте только при большом объёме данных (>100K записей)
  • LinkedHashMap сохраняет порядок вставки, если это важно
  • Кэшируйте результаты группировки при частых запросах

Выбор подхода зависит от версии Java, размера данных и требований к производительности.

Как сгруппировать записи таблицы по условию | PrepBro