partitioningBy() method in Java 8 Collectors API

In this article, we will learn the use of partitioningBy() method in Java 8 Collectors API with the help of examples.

Definition

This partitioningBy() method of the Collectors class is used to partition the stream of objects or elements based on a given predicate. This is a predefined method of java.util.stream.Collectors class.

Note* predicate interface accepts an argument, tests some conditions, and returns a true or false. If you want to learn more about predicate interface please refer to this article https://getinputs.com/predicate-interface-in-java-8/

Overloaded methods

The partitioningBy() method is overloaded in two ways

  • static < T > Collector < T, ?, Map < Boolean, List < T > > > partitioningBy(Predicate predicate)
  • static < T,D,A > Collector< T,?,Map< Boolean,D > > partitioningBy(Predicate < ? super T > predicate, Collector < ? super T,A,D > downstream)

1 ) static < T > Collector < T, ?, Map < Boolean, List < T > > > partitioningBy(Predicate predicate)

We can write this syntax in the below form for a better understanding

static <T> Collector<T, A, R> partitioningBy(Predicate predicate)

This method returns a Collector which partitions the input elements according to a predicate and organizes them into a Map<Boolean, List<T>>

T: Type of input elements that are going to be partitioned

A: Accumulator which accumulates the intermediate results of this reduction operation

R: Stores the end result of this operation

predicate: partitions the elements based on some condition

Ex: We will partition the List of people based on their age. If the age is an even number store the Person in one list. If the age is an odd number store the Person in a different list.

Person.java

package com.getinputs;

public class Person {

    String name;
    int age;

    Person(String name, int age) {
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.getinputs;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

public class Partitioning {
  static List < Person > createPeople() {
    List < Person > list = new ArrayList < > ();
    list.add(new Person("Suraj", 32));
    list.add(new Person("Iqbal", 34));
    list.add(new Person("Suchit", 25));
    list.add(new Person("Amar", 30));
    list.add(new Person("Kartik", 27));
    return list;
  }

  public static void main(String[] args) {
    List < Person > list = createPeople();
    Map < Boolean, List < Person >> map = list.stream()
      .collect(partitioningBy(person -> person.getAge() % 2 == 0));

    System.out.println(map);
  }
}

Output :

{false=[Person{name='Suchit', age=25}, Person{name='Kartik', age=27}], 
true=[Person{name='Suraj', age=32}, Person{name='Iqbal', age=34}, Person{name='Amar', age=30}]}

As we know the results will be stored in a map (i.e) key-value pair. Hence the even-numbered age persons are placed in a list with a key as true ( because the condition is == ) and all the odd-numbered age persons are placed in a list with a key as false.


2 ) static < T,D,A > Collector< T,?,Map< Boolean,D > > partitioningBy(Predicate < ? super T > predicate, Collector < ? super T,A,D > downstream)

This overloaded function takes 2 arguments

predicate: It partitions the elements based on some condition

downstream: This collector function furthermore reduces the results to generate a concrete output. The output will be in the form of a map. D can be of any type Ex. Integer, String, List, etc.

The downstream function which returns a list

The below downstream function will map the Person object to their age and collects the ages in a list

package com.getinputs;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import static java.util.stream.Collectors.*;

public class Partitioning {

  static List < Person > createPeople() {
    List < Person > list = new ArrayList < > ();
    list.add(new Person("Suraj", 32));
    list.add(new Person("Iqbal", 34));
    list.add(new Person("Suchit", 25));
    list.add(new Person("Amar", 30));
    list.add(new Person("Kartik", 27));
    return list;
  }

  public static void main(String[] args) {
    List < Person > list = createPeople();
    Map < Boolean, List < Person >> map = list.stream()
      .collect(partitioningBy(person -> person.getAge() % 2 == 0));

    System.out.println(map);

    Predicate < Person > predicate = (Person person) -> person.getAge() % 2 == 0;
    Map < Boolean, List < Integer >> printAges = list.stream()
      .collect(partitioningBy(predicate, mapping(Person::getAge, toList())));

    System.out.println(printAges);
  }
}

Output : 
{false=[Person{name='Suchit', age=25}, Person{name='Kartik', age=27}], true=[Person{name='Suraj', age=32}, Person{name='Iqbal', age=34}, Person{name='Amar', age=30}]}

{false=[25, 27], true=[32, 34, 30]}

The downstream function which returns a Long

The below downstream function will count the number of persons who are even-aged and odd-aged and returns the count of them.

package com.getinputs;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import static java.util.stream.Collectors.*;

public class Partitioning {

  static List < Person > createPeople() {
    List < Person > list = new ArrayList < > ();
    list.add(new Person("Suraj", 32));
    list.add(new Person("Iqbal", 34));
    list.add(new Person("Suchit", 25));
    list.add(new Person("Amar", 30));
    list.add(new Person("Kartik", 27));
    return list;
  }

  public static void main(String[] args) {
    List < Person > list = createPeople();
    Map < Boolean, List < Person >> map = list.stream()
      .collect(partitioningBy(person -> person.getAge() % 2 == 0));

    System.out.println(map);

    Predicate < Person > predicate = (Person person) -> person.getAge() % 2 == 0;
    Map < Boolean, Long > count = list.stream().collect(partitioningBy(predicate, counting()));

    System.out.println(count);
  }
}

Output :

{false=[Person{name='Suchit', age=25}, Person{name='Kartik', age=27}], true=[Person{name='Suraj', age=32}, Person{name='Iqbal', age=34}, Person{name='Amar', age=30}]}

{false=2, true=3}

I hope you found this article interesting and valuable. If you are having any concerns or questions about this article please comment below.

Leave a Comment