Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как разделить список на две части по условию

Короткий ответ

partitioningBy() создаёт Map с двумя ключами: true — элементы, подходящие под условие, false — остальные:

void main() {
    var numbers = List.of(1, 2, 3, 4, 5, 6, 7);
 
    Map<Boolean, List<Integer>> parts = numbers.stream()
            .collect(Collectors.partitioningBy(n -> n % 2 == 0));
    IO.println(parts.get(true));
    IO.println(parts.get(false));
}

Результат:

[2, 4, 6]
[1, 3, 5, 7]

С подсчётом

Второй аргумент обрабатывает каждую часть — например, считает элементы:

record Student(String name, int score) {}
 
void main() {
    var students = List.of(new Student("Anna", 85), new Student("Oleg", 40), new Student("Ivan", 62));
 
    var passed = students.stream()
            .collect(Collectors.partitioningBy(s -> s.score() >= 50, Collectors.counting()));
    IO.println(passed);
}

Результат:

{false=1, true=2}

Обе группы всегда есть

В отличие от groupingBy(), обе части есть даже тогда, когда одна из них пустая:

void main() {
    var numbers = List.of(2, 4, 6);
    IO.println(numbers.stream().collect(Collectors.partitioningBy(n -> n > 10)));
}

Результат:

{false=[2, 4, 6], true=[]}

Частая ошибка

Фильтровать список дважды — один раз по условию и второй раз по обратному. Это два прохода и повторённое условие, которое легко изменить только в одном месте. partitioningBy() делает всё за один проход.

Функции из этого ответа

  • Collectors.partitioningBy() — Делит элементы потока на две группы по условию.
  • Collectors.groupingBy() — Сборщик, который раскладывает элементы по группам с общим ключом.
  • Collectors.counting() — Сборщик-счётчик; обычно используется внутри `groupingBy()`.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.