Java Programs›Java 8 Streams›Partition a List Using partitioningBy

Partition a List Using partitioningBy in Java

intermediate·  Java 8 Streams  ·  Streams

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).

Input
[45, 78, 32, 90, 55, 49]
Output
Passed: [78, 90, 55], Failed: [45, 32, 49]

Java Program

Java
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

Passed: [78, 90, 55] Failed: [45, 32, 49]

Core Logic

partitioningBy takes a predicate and sorts every element into the true or false list in a single pass.

How It Works
  1. 1m -> m >= 50 is the predicate deciding which side each mark goes to.
  2. 2The result is a Map&lt;Boolean, List&lt;Integer&gt;&gt;.
  3. 3result.get(true) holds the passing marks and result.get(false) the failing ones.
  4. 4Both lists keep the original order of the marks.
78, 90 and 55 meet the 50-mark bar; 45, 32 and 49 do not.
💡

Key Point: Unlike groupingBy, partitioningBy always contains both keys — get(false) returns an empty list rather than null when nobody failed.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Each mark is tested once and stored in exactly one of the two lists.

Key Concepts

Collectors.partitioningBy()PredicateMap<Boolean, List>

Approach 2: Counting Each Side

Java
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

Passed: 3, Failed: 3

Core Logic

Adding a downstream collector replaces the lists with whatever summary you need — here, how many marks fell on each side.

How It Works
  1. 1partitioningBy(m -> m >= 50, Collectors.counting()) counts instead of collecting.
  2. 2The map's values become Long counts.
  3. 3Both counts are printed on one line.
Three marks pass and three fail.
💡

Key Point: Counting directly avoids building lists you only wanted the size of.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: One pass updates two counters.

Key Concepts

downstream collectorCollectors.counting()

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.

Learn the Concept

Related Programs