Definition
- partitioningBy(predicate) divides elements into exactly two groups: true and false.
- Always two keys: both true and false exist in the result, even if one side is empty.
- Even predicate:
n -> n % 2 == 0classifies even numbers as true, odd as false. - Downstream nesting: add
counting()to get counts per parity instead of full lists. - Result type:
Mapfor the default; changes with downstream.>
Priya at the National Bank of India splits transaction IDs into two processing lanes: even-numbered ones go to lane A and odd-numbered ones go to lane B. Both lanes always exist, even if one batch happens to have no even IDs.
Understanding the Concepts
What does this question ask?
The interviewer wants you to separate odd and even numbers using partitioningBy. This tests the distinction between partitioning and grouping, the guaranteed two-key result, and downstream collector nesting.
How do you partition into odd and even?
package com.bank.service;
import java.util.*;
import java.util.stream.Collectors;
public class OddEvenPartition {
public static void main(String[] args) {
List<Integer> transactionIds = List.of(
1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008);
Map<Boolean, List<Integer>> partition = transactionIds.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
System.out.println("Even: " + partition.get(true));
System.out.println("Odd: " + partition.get(false));
}
}
Even: [1002, 1004, 1006, 1008]
Odd: [1001, 1003, 1005, 1007]
Why partitioningBy instead of groupingBy on a boolean?
| Feature | partitioningBy | groupingBy(isEven) |
|---|---|---|
| Keys guaranteed | Both true and false always present | Missing key if no elements match |
| Null check needed | No | Yes, for missing key |
| Efficiency | Slightly optimized for binary split | General-purpose |
// partitioningBy: both keys always exist
Map<Boolean, List<Integer>> partition = List.<Integer>of().stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
System.out.println(partition.get(true)); // [] (empty list, not null)
System.out.println(partition.get(false)); // [] (empty list, not null)
// groupingBy on boolean: missing keys possible
Map<Boolean, List<Integer>> group = List.<Integer>of().stream()
.collect(Collectors.groupingBy(n -> n % 2 == 0));
System.out.println(group.get(true)); // null!
System.out.println(group.get(false)); // null!
How do you nest a downstream collector?
// Count per parity
Map<Boolean, Long> counts = transactionIds.stream()
.collect(Collectors.partitioningBy(
n -> n % 2 == 0,
Collectors.counting()));
System.out.println("Even count: " + counts.get(true));
System.out.println("Odd count: " + counts.get(false));
Even count: 4
Odd count: 4
How do you use partitioning for pass/fail classification?
package com.bank.service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
public class ThresholdPartition {
public static void main(String[] args) {
List<BigDecimal> balances = List.of(
new BigDecimal("50000"),
new BigDecimal("125000"),
new BigDecimal("75000"),
new BigDecimal("25000"));
BigDecimal threshold = new BigDecimal("50000");
Map<Boolean, List<BigDecimal>> partition = balances.stream()
.collect(Collectors.partitioningBy(
b -> b.compareTo(threshold) >= 0));
System.out.println("Above threshold: " + partition.get(true));
System.out.println("Below threshold: " + partition.get(false));
}
}
Above threshold: [50000, 125000, 75000]
Below threshold: [25000]
What are common mistakes?
Mistake: using groupingBy when partitioningBy is more appropriate.
// WRONG for binary split: groupingBy may have missing keys
Map<Boolean, List<Integer>> wrong = List.of(1, 3, 5).stream()
.collect(Collectors.groupingBy(n -> n % 2 == 0));
List<Integer> evens = wrong.get(true); // null!
// CORRECT: partitioningBy guarantees both keys
Map<Boolean, List<Integer>> correct = List.of(1, 3, 5).stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
List<Integer> safeEvens = correct.get(true); // [] (empty, not null)
Mistake: confusing the parity test direction.
// Check which key holds evens vs odds
// n % 2 == 0 → true = even, false = odd
// n % 2 != 0 → true = odd, false = even (reversed!)
When should you use groupingBy instead?
Use groupingBy when there are more than two categories.
// Three categories: negative, zero, positive
Map<String, List<Integer>> threeWay = List.of(-5, 0, 3, -2, 7).stream()
.collect(Collectors.groupingBy(n ->
n < 0 ? "negative" : n == 0 ? "zero" : "positive"));
What are common interview follow-up questions?
- "How do you partition employees by salary above/below a threshold?" Same pattern with a salary comparison predicate.
- "How do you get both the list and the count?" Use collectingAndThen or process the partition result.
- "Can you partition by more than one condition?" Not directly; use groupingBy with a multi-valued classifier.
Visual Overview
List: [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008]
│
│ partitioningBy(n -> n % 2 == 0)
▼
┌───────────────────────────────────────────┐
│ true (even): [1002, 1004, 1006, 1008] │
│ false (odd): [1001, 1003, 1005, 1007] │
└───────────────────────────────────────────┘
Both keys always present, even if one side is empty
Key Takeaway
Separating odd and even numbers uses partitioningBy with an even predicate, which divides the stream into exactly two buckets keyed by true and false. The defining feature of partitioningBy is that it always produces both keys, so even if every number is odd, the true list still exists as an empty list.
That guarantee is why partitioningBy is preferred over groupingBy on a boolean for binary splits. groupingBy could omit an empty side and force a null check, while partitioningBy lets you safely read both lanes. A downstream collector like counting() can be nested for counts per side.
At the National Bank of India, Rajesh used this to split transaction IDs into even and odd for two parallel processing lanes, ensuring both lanes always have a valid (possibly empty) list.
Remember one sentence: partitioningBy always produces both true and false keys, making it the right tool for binary classification like odd/even.
---