Hey, tea lovers! Today I will be talking about the partitioningBy Collector method of Stream API. I will be focusing on what is partitioningBy by method, where, and how to use it with different examples. I have already discussed How to use groupingBy Collector in Java Streams. Both partitioningBy and groupingBy are the
. java.util.stream.Collectors
partitioningBy
is a terminal operation of the Stream API pipeline.
I would be happy to connect with you guys on social media. It’s @coderstea on Twitter, Linkedin, Facebook, Instagram, and YouTube.
Please Subscribe to the newsletter to know about the latest posts from CodersTea.
Prerequisites
The partitioningBy is the Stream API method, so obviously you should be familiar with Stream API along with functional programming with Java. Don’t worry if you don’t know about it, you can check the Functional Interfaces To Become More Functional in Java and Stream API: The Hero Without a Cape post in the same order. These posts will be enough for you to get started.
Why Use partitioningBy Collector
Sometimes, you need to see if the element of the collection is fulfilling a certain condition. But, we don’t want to skip or remove the failed elements, instead, we just want to partition them into true and false buckets. The Stream filter
can be used to check if the object or element is passing the condition or not. However, it blocks objects which fail the condition. So you only get a true or false derived object in the next pipe depending on the condition, which we don’t want.
So our option is to do this via the imperative style of programming like using a map, a loop, and in the if statement populating that map (one of many solutions). What if you can do all these steps in a single statement? How reduced your code will be? And the side effect will be a much more readable, maintainable, and self-explanatory code, isn’t it? That statement is partitioningBy. In its simplest form, just provide the condition, and that’s it. It takes care of all the things and gives you a Map of Boolean and the List i.e Map<Boolean, List<T>>>
. Now let’s see it HOW.
How to Use partitioningBy Collector
To use them partitioningBy,
you have to pass the Collectors.partitioningBy
in the collect()
method of Stream API. Like the following,
numberList.stream().collect(Collectors.partitioningBy(num -> num % 2 ==0));
Unlike groupingBy
, discussed here, partitioningBy
is simple. It mainly requires the Predicate as a parameter, and if you want to do some operation on the sublist then another param of Collector can be added.
// create a sublist
partitioningBy(Predicate<T> predicate)
// do operaton on the partition
partitioningBy(Predicate<T> predicate, Collector<T, A, D> downstream)
Code language: JavaScript (javascript)
Don’t worry we will take a look at them one by one by example.
Using partitioningBy Collector to Separate the List
Let’s talk about the first one i.e partitioningBy(Predicate<T> predicate)
. Learn more about the Predicate here. As I said, using this Predicate you simply partition the list into true or false sublists. Here is an example, of how you can use it to separate the list based on some conditions.
Partition Even and Odd Numbers In-Stream API
The following program would separate the odd and even numbers in the map with false and true keys respectively.
List<Integer> numberList = Arrays.asList(0,1,2,3,4,5,6,7,8,9);
// partitionBy even numbers
// true sublist will be even numbers and false will be odd numbers
Map<Boolean, List<Integer>> evenNumberMap = numberList.stream()
.collect(Collectors.partitioningBy(num -> num % 2 == 0));
System.out.println("The Even Numbers are" + evenNumberMap.get(true));
Code language: JavaScript (javascript)
Separate the Numbers Greater and Less than n
Let’s say, now you want to separate the numbers if they are greater than or equal to 5. Here is how you can do it with partitioningBy.
// partitioningBy numbers greater than and less than 5
Map<Boolean, List<Integer>> gt5Map = numberList.stream()
.collect(Collectors.partitioningBy(num -> num >= 5));
System.out.println("The Numbers Greater than or equal to 5 are" + gt5Map.get(true));
System.out.println("The Numbers Less than 5 are" + gt5Map.get(false));
Code language: JavaScript (javascript)
And like this, you can play according to your requirements. Now let us see how to act the sublist.
Perform DownStream Operations on partitioningBy List
Now, you just don’t want to have the sublist but want to have a computed value in the map. Such as max value within the sublist or average, or some other Collector operation. The syntax for the downstream operation is as follows.
partitioningBy(Predicate<T> predicate, Collector<T, A, D> downstream)
Code language: HTML, XML (xml)
Here are a few examples to get you started.
Get the Average using partitioningBy
I will use the same number list. Now instead of generating the odd or even sublist, I will compute the average of it in the Map. To do the average we will use the Collectors.averagingInt
and pass the value with Integer::intValue
to pass it as a int
.
// partitioningBy odd and even with their average
// partitioningBy odd and even with their average
Map<Boolean, Double> oddEvenAverage = numberList.stream()
.collect(Collectors.partitioningBy(
num -> num % 2 != 0,
Collectors.averagingInt(Integer::intValue)
));
System.out.println("Odd numbers average is " + oddEvenAverage.get(true));
System.out.println("Even numbers average is " + oddEvenAverage.get(false));
Code language: JavaScript (javascript)
partitioningBy to Get Set instead of List
Now you don’t want to have a List, but rather a Set. Just pass the `
// partitioningBy odd even with Set
Map<Boolean, Set<Integer>> oddEvenSet = numberList.stream()
.collect(Collectors.partitioningBy(
num -> num % 2 != 0,
Collectors.toSet()
));
Code language: JavaScript (javascript)
Nested partitioningBy Collector
I want to have numbers separated by if it is greater or equal to 5. After separation, I again want to separate the odd and even numbers. Here is how I will do it.
// partitioningBy greater or equal to 5 and then
// partitioningBy even and odd
Map<Boolean, Map<Boolean, List<Integer>>> gte5EvenOddMap = numberList.stream()
.collect(Collectors.partitioningBy(
num -> num >= 5,
Collectors.partitioningBy(
num -> num % 2 == 0
//again can add more partitioningBy...
)
));
System.out.println("Odd numbers Greater than 5 are "
+ gte5EvenOddMap.get(true).get(false));
System.out.println("Even numbers Greater than 5 are "
+ gte5EvenOddMap.get(true).get(true));
System.out.println("Even numbers Less than 5 are "
+ gte5EvenOddMap.get(false).get(true));
Code language: JavaScript (javascript)
With this 2nd parameter, downstream Collector, you can be so much more creative according to your need. I can keep going with different examples but I think these are enough to understand the concept.
Conclusion
That’s it for this post. Hope you have understood how to use partitioningBy Collector in Stream API. The full code is available on GitHub. If you liked the post or if you have any queries about this, please let me know in the comment. You can follow me on social media @coderstea on Twitter, Linkedin, Facebook, or Instagram. You can also publish your post on coderstea, just share your thought on Contact Us.
See you in the next post. HAKUNA MATATA!!!
I would be happy to connect with you guys on social media. It’s @coderstea on Twitter, Linkedin, Facebook, Instagram, and YouTube.
Please Subscribe to the newsletter to know about the latest posts from CodersTea.