Partition a List Using partitioningBy in Java
Problem
Partitioning is grouping with a yes-or-no question: every element goes into either the true group or the false group, so the result always has exactly two keys.
Given a list of marks, split them into marks of 50 or more (passed) and marks below 50 (failed).
Java Program
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class PartitionNumbers {
public static void main(String[] args) {
List<Integer> marks = Arrays.asList(45, 78, 32, 90, 55, 49);
Map<Boolean, List<Integer>> result = marks.stream()
.collect(Collectors.partitioningBy(m -> m >= 50)); // always exactly two groups
System.out.println("Passed: " + result.get(true));
System.out.println("Failed: " + result.get(false));
}
}Output
Core Logic
partitioningBy takes a predicate and sorts every element into the true or false list in a single pass.
- 1
m -> m >= 50is the predicate deciding which side each mark goes to. - 2The result is a
Map<Boolean, List<Integer>>. - 3
result.get(true)holds the passing marks andresult.get(false)the failing ones. - 4Both lists keep the original order of the marks.
Key Point: Unlike groupingBy, partitioningBy always contains both keys — get(false) returns an empty list rather than null when nobody failed.
Why: Each mark is tested once and stored in exactly one of the two lists.
Key Concepts
Approach 2: Counting Each Side
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class PartitionNumbersCounting {
public static void main(String[] args) {
List<Integer> marks = Arrays.asList(45, 78, 32, 90, 55, 49);
Map<Boolean, Long> counts = marks.stream()
.collect(Collectors.partitioningBy(m -> m >= 50, Collectors.counting()));
System.out.println("Passed: " + counts.get(true) + ", Failed: " + counts.get(false));
}
}
Output
Core Logic
Adding a downstream collector replaces the lists with whatever summary you need — here, how many marks fell on each side.
- 1
partitioningBy(m -> m >= 50, Collectors.counting())counts instead of collecting. - 2The map's values become
Longcounts. - 3Both counts are printed on one line.
Key Point: Counting directly avoids building lists you only wanted the size of.
Why: One pass updates two counters.
Key Concepts
Interview Questions
When should you use partitioningBy instead of groupingBy?
When there are exactly two groups, true and false. partitioningBy always contains both keys, even if one group is empty.
Can partitioningBy count or sum the groups?
Yes. A downstream collector such as counting() or summingInt(...) replaces the lists with totals.