How to Deal with Java 8 Stream API (Cont.)
Well, well. It seems I post faster that I thought regarding the additional Stream API functionalities. Soon after I published the stream how-to, a friend of mine came and gave me a feedback, or request precisely, about the functionalities which I did not discuss. Also, he thought my post was like an unfinished business. So Roberto, this one for fulfilling your special request :).
Match Operation
Whenever you are doing computational process through a collection, sometimes you need to know whether it contains specific object or not. Or maybe you want to acknowledge whether a collection contains all objects you need or not. Stream API comes with three match functions for these needs. Those are anyMatch
, allMatch
and noneMatch
. Here are the samples:
Flat Map
In other cases, maybe you have a stream which contains many collections. And you want to access those collections with a singleĀ operation. For this purpose, you can use the flatMap
operation. It basically transforms each element in stream into another stream objects.
For instance, I have two lists. The first one contains positive numbers and the other one contains negative numbers. My purpose is to get the odd numbers from both lists within one single stream operation.
Reduce
When you are working with a set of data, occasionally you need to accumulate them into one single value. Such operations, like min
or max
, which return number. But, what about if we want to get total sum of all numbers in the stream? Or String operation? To answer these questions, Stream API offers reduce operation to facilitate our needs.
Reduce operation itself has three types. The first one is the simplest one. It only accepts BinaryOperator
as an accumulator function. Put your logic to combine the stream into single operation under this function. For example, I want to display all Car models into one single line with separator |. Note: I still use the list of Cars example from previous post.
The second one is reduce method with two parameters. The identity value and BinaryOperator
accumulator. The accumulator will use the identity value for first accumulation process. I said first because we don’t use parallelStream
yet. The next sample is more or less similar with the previous one, but the different is I want to have Renault in the beginning of my result.
I already mentioned a little bit about parallelStream
in the previous paragraph. Now, we can try to use parallelStream
into our second reduce sample.
Errr… the result is not what I expected. I have four Renaults! (Wow.. I must be rich). So what is going on here?
Parallel Stream
Stream API has another type of streams, which is a parallel one. Parallel stream offers faster execution if you are processing huge number of data. But be careful with its overhead, just like the four Renaults sample.
In order to handle the parallel stream problem with reduce operation, we need another and the last type of reduce. It offers three parameters: initial value, BiFunction as an accumulator and BinaryOperator as a combiner. Now we have to remove the rest of three Renaults using this last reduce type.
Should we go parallel instead of sequential stream? My opinion, it is better to use sequential stream as much as you can, unless you have a performance problem. Because you need additional logic to handle the multiple processes. But, I open to any discussion about this preferences.
Stream Reuse
Once the terminal operation is executed, stream is closed and cannot be reused. It will throw IllegalStateException
whenever you try to call after the stream is closed.
However, we have a workaround for this problem. Either you create another stream instance, or more elegant way, using Supplier
class.
Conclusion
So, that’s all of my promise to post the rest of Stream API operations. I hope it will help you to know more about stream features. Happy coding then!