One of the cool new features in upcoming Java 8 release is the update to the the Collections API with the new Streams API.
Say if I have a Project class with an isCompleted method. If want a list of all completed projects. Now I want to retrieve a list of projects that have been completed.
Using Java 6 I could do this….
for (Project project : allProjects) {
if (project.isCompleted()) {
completedProjects.add(project);
}
}
The above is correct and would work, few criticism of this way, many people (especially with functional language background) would argue its very verbose for what it’s doing, the problem that I’m trying to solve is just to get the released projects – ( do I need to specify it needs to be done in a loop?).
So a few issues with the above
- Have to do the filtering using a loop, is something I shouldn’t have to decide, instead I should delegate it to library to decide the best implementation
- The looping used above is sequential, so doesn’t take advantage of multi-cores in todays machines
- Being pedantic, I had to mention the the type “Project” 3 times in this simple code (ok, with Java 7 Diamonds you could reduce it to 2).
The Java 8 Way of doing this would be..
.filter(project -> project.isCompleted())
.collect(Collectors.toList());
Now the stream library is free to decide if it’s going to use sequential loop or use some clever algorithm to best use the CPU on the machine. i also like the fact, I only have to mention the type “Project” once in all of this.
What confused me at first, is why the .collect is required the end. The way I think about this, is that Stream API could be applying the filter in parallel, so you need a collector at the end to pickup all of those results from the filters and place them into the result list.
The neat thing about the streams, is that you add other stuff onto the pipeline, say, I want to get the sorted list of completed projects…
.filter(project -> project.isCompleted())
.sorted()
.collect(Collectors.toList());
