Partition Even and Odd Numbers

Java coding interview problem for Java 8 Streams: Partition Even and Odd Numbers.

Partitioning a collection into two groups is a common Java Stream API interview problem.

A very common example:

Separate Even Numbers

and

Odd Numbers

This problem introduces:

  • Stream API
  • Predicate
  • Collectors.partitioningBy()
  • Functional programming
  • Data grouping techniques

What is Partitioning?

Partitioning means dividing a collection into two groups based on a condition.

The condition returns:

true

or

false

Example:

Numbers:

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

Condition:

number % 2 == 0

Result:

true  → Even Numbers

false → Odd Numbers

Understanding Even and Odd Numbers

A number is:

Even

If divisible by 2.

Example:

2

4

6

8

Condition:

number % 2 == 0

Odd

If not divisible by 2.

Example:

1

3

5

7

Condition:

number % 2 != 0

Why This Problem is Important?

This problem tests:

1. Stream API Knowledge

Understanding:

stream()

filter()

collect()

2. Functional Programming

Using:

Lambda expressions

Predicates

3. Collector Understanding

Especially:

Collectors.partitioningBy()

4. Data Processing Patterns

The same approach applies to:

  • Employee classification
  • Transaction filtering
  • Order processing
  • Validation rules

Array Partitioning Concept

Traditional approach:

Input Array

     ↓

Loop Through Elements

     ↓

Check Condition

     ↓

Store Result

Stream approach:

Collection

     ↓

Stream

     ↓

Predicate

     ↓

Partition

     ↓

Result Map

Real-World Applications

Employee Management

Partition employees:

Salary > $100,000

Salary <= $100,000

Banking Systems

Partition transactions:

Successful

Failed

E-Commerce

Partition orders:

Delivered

Pending

Security Systems

Partition users:

Active

Inactive

Problem Statement

Given a list of integers, partition numbers into:

Even Numbers

and

Odd Numbers

using Java Streams.


Input Example

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

Expected Output

Even:

[2,4,6,8]


Odd:

[1,3,5,7]

Partitioning Visualization

Input:

1 2 3 4 5 6

Condition:

number % 2 == 0

Processing:

1 → false

2 → true

3 → false

4 → true

5 → false

6 → true

Result:

true:

[2,4,6]


false:

[1,3,5]

Approach 1 — Traditional Loop Approach

Before Streams, developers commonly used loops.


Algorithm

  1. Create two lists.
  2. Traverse numbers.
  3. Check even/odd condition.
  4. Add to corresponding list.

Java Program

import java.util.*;

public class PartitionEvenOdd {


    public static Map<String,List<Integer>>
    partition(List<Integer> numbers) {


        List<Integer> even =
                new ArrayList<>();


        List<Integer> odd =
                new ArrayList<>();


        for(Integer number : numbers) {


            if(number % 2 == 0) {


                even.add(number);


            } else {


                odd.add(number);

            }

        }


        Map<String,List<Integer>> result =
                new HashMap<>();


        result.put(
            "Even",
            even
        );


        result.put(
            "Odd",
            odd
        );


        return result;

    }

}

Dry Run

Input:

[1,2,3,4,5]

Initial:

Even = []

Odd = []

Read:

1

Odd:

[1]

Read:

2

Even:

[2]

Read:

3

Odd:

[1,3]

Read:

4

Even:

[2,4]

Read:

5

Odd:

[1,3,5]

Final:

Even:

[2,4]


Odd:

[1,3,5]

Complexity Analysis — Loop Approach

Let:

n = number of elements

Traversal:

O(n)

Adding elements:

O(1)

Total Time:

O(n)

Space:

O(n)

because two lists are created.


Approach 2 — Using Stream filter()

A simple Stream solution uses two filters.


Even Numbers

List<Integer> evenNumbers =

numbers.stream()

.filter(
    number ->
    number % 2 == 0
)

.toList();

Odd Numbers

List<Integer> oddNumbers =

numbers.stream()

.filter(
    number ->
    number % 2 != 0
)

.toList();

Complete Example

import java.util.*;


public class EvenOddUsingStreams {


    public static void main(String[] args) {


        List<Integer> numbers =
                Arrays.asList(
                    1,2,3,4,5,6
                );


        List<Integer> even =
                numbers.stream()

                .filter(
                    n -> n % 2 == 0
                )

                .toList();


        List<Integer> odd =
                numbers.stream()

                .filter(
                    n -> n % 2 != 0
                )

                .toList();


        System.out.println(even);

        System.out.println(odd);

    }

}

Output

[2,4,6]

[1,3,5]

Problem With Two filter() Calls

The above solution works.

But it processes the stream twice.


Flow:

First traversal:

Find Even

Second traversal:

Find Odd

For large collections:

More processing

Better solution:

partitioningBy()

Approach 3 — Using Collectors.partitioningBy()

Java provides a collector specifically for two-way partitioning.


Syntax:

Collectors.partitioningBy(
    Predicate
)

Example:

Collectors.partitioningBy(
    number -> number % 2 == 0
)

Meaning:

true  → Even

false → Odd

Java Program — partitioningBy()

import java.util.*;
import java.util.stream.Collectors;


public class PartitionUsingStreams {


    public static Map<Boolean,List<Integer>>
    partition(List<Integer> numbers) {


        return numbers.stream()

                .collect(

                    Collectors.partitioningBy(

                        number ->
                        number % 2 == 0

                    )

                );

    }

}

Output

Input:

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

Output:

{
 true=[2,4,6],

 false=[1,3,5]
}

Step-by-Step Explanation

Input:

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

Condition:

number % 2 == 0

Process:

1 → false

2 → true

3 → false

4 → true

5 → false

6 → true

Collector creates:

true:

[2,4,6]


false:

[1,3,5]

Stream Pipeline

List<Integer>

      ↓

stream()

      ↓

partitioningBy()

      ↓

Predicate Evaluation

      ↓

Map<Boolean,List<Integer>>

Complexity Analysis

Traversal:

O(n)

Partition insertion:

O(1)

Total:

O(n)

Space:

O(n)

Advantages

  • Single traversal.
  • Clean and readable.
  • Designed specifically for two groups.
  • Works well with Stream API.

Drawbacks

  • Returns Boolean keys.
  • Requires understanding Collector API.
  • Not suitable for more than two groups.

Deep Dive into Collectors.partitioningBy()

Collectors.partitioningBy() is a special Stream collector used when data needs to be divided into exactly two groups.

The two groups are based on:

Predicate Result

which returns:

true

or

false

partitioningBy() Syntax

Basic syntax:

Collectors.partitioningBy(
    Predicate
)

Example:

numbers.stream()

.collect(

Collectors.partitioningBy(
    n -> n % 2 == 0
)

);

Result:

true  → Even Numbers

false → Odd Numbers

Internal Working

When Stream processes elements:

Element

   ↓

Predicate Check

   ↓

true / false

   ↓

Store In Bucket

Example:

Input:

[1,2,3,4]

Predicate:

n -> n % 2 == 0

Processing:

1 → false

2 → true

3 → false

4 → true

Buckets:

true:

[2,4]


false:

[1,3]

Difference Between partitioningBy() and groupingBy()

Both methods group data, but their purpose is different.


partitioningBy()

Used when there are:

Only two groups

Example:

Even

Odd

Returns:

Map<Boolean,List<T>>

Example:

{
 true=[2,4,6],

 false=[1,3,5]
}

groupingBy()

Used when there can be:

Multiple groups

Example:

Employee departments:

IT

HR

Finance

Returns:

Map<Key,List<Value>>

Comparison Table

Feature partitioningBy() groupingBy()
Groups Two Multiple
Condition Predicate Classifier Function
Key Type Boolean Any Type
Example Even/Odd Department
Use Case Binary split Category grouping

Custom Partition Conditions

Partitioning is not limited to even and odd numbers.

Any boolean condition can be used.


Example — Partition Positive and Negative Numbers

Input:

[-5,-2,0,3,8]

Condition:

n -> n >= 0

Java:

Map<Boolean,List<Integer>> result =

numbers.stream()

.collect(

Collectors.partitioningBy(
    n -> n >= 0
)

);

Output:

true:

[0,3,8]


false:

[-5,-2]

Partition Numbers Into Prime and Non-Prime

Example:

Input:

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

Condition:

isPrime(number)

Prime Check Method

public static boolean isPrime(int number) {


    if(number <= 1) {

        return false;

    }


    for(int i = 2;
        i <= Math.sqrt(number);
        i++) {


        if(number % i == 0) {

            return false;

        }

    }


    return true;

}

Partition Using Predicate

Map<Boolean,List<Integer>> result =

numbers.stream()

.collect(

Collectors.partitioningBy(
    NumberPartition::isPrime
)

);

Output:

true:

[2,3,5,7]


false:

[4,6]

Partition Employees by Salary

Real-world example:

Separate:

High Salary Employees

Low Salary Employees

Employee:

John    90000

Alice  150000

Bob    70000

Condition:

salary >= 100000

Java Program

Map<Boolean,List<Employee>> result =

employees.stream()

.collect(

Collectors.partitioningBy(

employee ->
employee.getSalary() >= 100000

)

);

Output:

true:

Alice


false:

John

Bob

Partition Objects Using Streams

Streams can partition any object type.

Examples:

Orders

Completed

Pending

Users

Active

Inactive

Transactions

Success

Failure

Example:

Collectors.partitioningBy(
    Transaction::isSuccessful
)

Multiple Partition Levels

Sometimes applications need nested partitioning.

Example:

Employees:

Salary

+

Department

First partition:

High Salary

Low Salary

Then group:

Department

Example:

employees.stream()

.collect(

Collectors.partitioningBy(

Employee::isHighSalary,

Collectors.groupingBy(
    Employee::getDepartment
)

)

);

Result:

true:

 IT → employees

 HR → employees


false:

 IT → employees

 Finance → employees

Custom Predicate Examples

A Predicate represents:

Input

 ↓

true / false

Example 1 — Age Classification

Predicate<Person> adult =
        person ->
        person.getAge() >= 18;

Partition:

Adults

Minors

Example 2 — Product Availability

product ->
product.getStock() > 0

Result:

Available

Out Of Stock

Stream vs Loop Comparison

Feature Loop Stream
Code More Less
Readability Simple Declarative
Performance Slightly faster Comparable
Parallel Processing Manual Supported
Functional Style No Yes

Parallel Stream Considerations

For large collections:

parallelStream()

can process data using multiple threads.


Example:

numbers.parallelStream()

.collect(

Collectors.partitioningBy(
    n -> n % 2 == 0
)

);

However:

Consider:

  • Data size
  • Thread overhead
  • Order requirements

For small lists:

Normal stream()

is usually better.


HashMap Internal Working

partitioningBy() internally creates a map structure.

Conceptually:

Map<Boolean,List<T>>

        |

        +------ true bucket

        |

        +------ false bucket

Example:

true

 |

[2,4,6]


false

 |

[1,3,5]

Common Interview Mistakes

Mistake 1

Using groupingBy for binary conditions.

Example:

Even/Odd

Better:

partitioningBy()

Mistake 2

Expecting more than two groups.

Wrong:

partitioningBy(department)

Use:

groupingBy()

Mistake 3

Forgetting Boolean keys.

Result:

Map<Boolean,List<T>>

not:

List<List<T>>

Mistake 4

Using parallel streams unnecessarily.

For small data:

parallelStream()

may reduce performance.


Edge Cases

Case Handling
Empty list Returns empty true/false lists
All even False list empty
All odd True list empty
Null values Filter before partition
Large data Consider parallel streams

Interview Follow-up Questions

Q1. Difference between partitioningBy() and groupingBy()?

Q2. How does partitioningBy work internally?

Q3. Partition employees by salary range.

Q4. Can partitioningBy create more than two groups?

Q5. How to combine partitioningBy with groupingBy?

Q6. How to partition custom objects?

Q7. What is the return type of partitioningBy()?


Related Java Collection Problems

  • Group Employees by Department
  • Find Duplicate Elements Using Streams
  • Character Frequency Using Streams
  • Find Highest Salary Employee
  • Convert List to Map
  • Custom Comparator Examples

Key Takeaways

Partitioning pattern:

Collection

     ↓

Predicate

     ↓

true / false

     ↓

Two Groups

Use:

Two groups

Collectors.partitioningBy()

Use:

Multiple groups

Collectors.groupingBy()

Examples:

Even/Odd:

n -> n % 2 == 0

Salary:

employee ->
employee.getSalary() >= 100000

Order:

transaction ->
transaction.isCompleted()

Complexity:

Time:

O(n)

Space:

O(n)

Frequently Asked Interview Questions

Q1. What does partitioningBy return?

A:

Map<Boolean,List<T>>

Q2. Why use partitioningBy instead of groupingBy?

A:

Because the result has exactly two groups based on a condition.


Q3. Can partitioningBy work with objects?

A:

Yes. Any object can be partitioned using a Predicate.


Q4. Is partitioningBy faster than groupingBy?

A:

For binary classification, partitioningBy is more expressive and optimized for the use case.


Interview Tip

When asked:

"Partition data using Java Streams."

Explain:

  1. Identify the true/false condition.
  2. Use Collectors.partitioningBy().
  3. For more than two categories use groupingBy().
  4. Combine collectors for complex reporting.
  5. Discuss performance and parallel processing.

For senior Java interviews, discuss:

  • Predicate design.
  • Collector internals.
  • Nested collectors.
  • Stream performance.
  • Enterprise data classification patterns.

This demonstrates strong understanding of Java Streams, Collectors, and functional programming techniques.