Комментарии (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, размера данных и требований к производительности.