I’ve been in Java world since its 1.2.1 version. And I’ve been using all their major release version, until 8.0 recently. Therefore, I have noticed a couple game changers in several releases. Well, take a note here, game changer means changing the way how to code.
The first one was the release of JDK 5.0, with its annotations. Before it was released, almost every configuration was in the XML format (Spring or Hibernate for example). But now, as you can see, annotations are everywhere.
The second one is the 8th version. They brought functional programming into the so called object oriented programming. In order to support this new paradigm, Java came along with new features such as lambda, default interface method, functional interface and the Stream API.
Based on their website, stream is a sequence of elements from a source that supports aggregate operations. The definition itself tells about source of sequence elements. So, naturally,
java.util.Collection will pop up in your mind. It is a valid one, because now Collection interface has default interface methods related to stream. Those are
parallelStream(). However, Stream is not Collection and vice versa. In a simple term, Collection is about data and Stream is about computation.
Stream can be populated via multiple data sources. The first one, of course, comes from
java.util.Collection. The other one comes from
java.util.Arrays class. Also you can create from special stream objects. Java 8 already ships the built-in stream builder, based on primitive data types. They are
DoubleStream. Besides, it provides the builder from the
java.util.Stream interface itself. So here are samples for each stream builder.
Stream has two types of operations, which are intermediate and terminal. Intermediate operations return a stream itself, so it can do operation chaining. In the first sample, the intermediate operation is a
map method. Meanwhile, the terminal operation results a side effect. The side effect can be void or return a value. If you see the sample, the
ifPresent methods are the terminal operations.
Simple Stream Usage
Now into the stream usage. For example, I have a list of integers which contains random numbers. I need to filter out all the odd numbers, then power them by 2. Here is the second sample.
Unless you are very lucky, you will see the order a little chaotic. Also rarely you will find duplicate numbers. To address this ‘problem’, we need two additional requirements. First, remove duplicate number and the other one is sorting the result. Of course, we will address in the stream-esque style.
So far we have learned the most common operations usage in stream, such as map and filter. There are still plenty of operations, such as
min, etc. You can discover yourself under Stream API to get deeper knowledge regarding Stream.
It is time to move to one of the nicest feature of this stream things. It is a
Collectors object. We can use this object with one of terminal operation, which is the
For the next collector example, we will refer to the Car class as show below.
Now for the collector part. The next sample will show how to use the collector, from basic usage such as convert stream to list until getting statistics summary.
I finish this Stream API how-to just until this part. At least for now. I know there are still plenty things to be discussed. For instance the usage of
parallelStream and class related to stream itself, such as
Supplier class. No promise, but I have a plan to bring those topics into my blog somewhere in the future.
I will leave those things to you to play around. Have fun and have a good stream experience.