The Streams API introduced in Java SE 8 is a set of operations which can be applied on collections to express complex queries to process data.
We come across collections in programs often. Such as an array of products for an e-commerce website or a set of transactions for a customer of a bank or a file containing many lines of text.
Consider the example: A user of an online bookstore wants to see a list of all second hand ‘Harry Potter’ books sorted by prices from cheapest onwards available at the store.
To answer the query, following Stream operations are required:
- Filter all available books by the title ‘Harry Potter’
- Sort the resulting stream from point 1 above by prices in ascending order.
- Collect the resulting filtered and sorted stream into a collection.
We can answer the above business requirement with the following SQL query:
select title, price
from Books
where title='Harry Potter'
order by price ASC;
Now consider the ‘older’ method of answering the above query without the Streams API explicitly using loops:
List harryPotterBooks = new ArrayList<>();
for (Book book:
listOfBooks) {
if (book.getTitle().equals("Harry Potter")){
harryPotterBooks.add(book);
}
}
harryPotterBooks.sort(new Comparator() {
@Override
public int compare(Book o1, Book o2) {
if (o1.getPrice() > o2.getPrice()){
return 1;
} else if(o1.getPrice() < o2.getPrice()){
return -1;
}else return 0;
}
});
System.out.println("Printing sorted Harry Potter books by price asc");
for (Book book:
harryPotterBooks) {
System.out.println(book.toString());
}
Now consider the same business requirement implemented using the Streams API:
List harryPotterBooks = new ArrayList<>();
harryPotterBooks = listOfBooks.stream()
.filter(b -> b.getTitle() == "Harry Potter")
.sorted(comparing(Book::getPrice))
.collect(Collectors.toList());
harryPotterBooks.forEach(System.out::println);
Over here, the stream(), filter(), sorted(), collect() and forEach() methods are Stream API operations.
Just to revisit, the business requirement implemented using the SQL solution looked like this:
select title, price
from Books
where title='Harry Potter'
order by price ASC;
As can be seen, both the SQL solution and the solution using the Streams API solve the business requirement by declaratively expressing what needs to be done (by using lambda expressions), rather than imperatively expression how we should filter the input, sort it, collect and print the output using for loops.
Hope this small introduction into the Streams API is useful in clarifying the difference between the use of Streams API and explicitly using loops to perform operations on collections.
The complete code example can be found here: https://github.com/zeesh49/Java_Streams_API
In the next post, we will discuss the Streams API in more detail.
