Wednesday, February 8, 2017

Java 8 Stream API

In this article we will understand and learn about Stream API in Java 8 Version. This is one of core concept in Core Java. Java 8 brings new abilities to work with Collections,in the form of a brand new Stream API. This new functionality is provided by the java.util.stream package. 

The Stream API offers easy filtering,counting and mapping of Collections as well as different ways to get slices and subsets of information out of them. The Stream API allows shorter and more elegant code for working with collections.

Stream represents a sequence of objects. A stream operates on data source,such as an array or Collections. A stream never provides storage for the data. It simply moves the data,possibly filtering,sorting on that data in the process.

The Stream API defines several stream interfaces, which are packaged in java.util.stream

BaseStream is a generic interface declared like this:

interface BaseStream<T, S extends BaseStream<T,S>>

In the above T specifies the type of elements in the stream, and S represents the type of stream that extends BaseStream. BaseStream extends AutoCloseable interface,thus a stream can be managed in try-with-resources statement.

How to obtain a Stream:

You can obtain a stream in a number of ways. Perhaps the most common is when a stream is obtained for a collection. In JDK 8, the Collection interface has been expanded to include two methods that obtain a stream from a collection. The first is stream() as shown below

default Stream<E>stream()

The second method is

 default Stream<E>parallelStream()

A stream can be obtained from an array by use of the static stream() method,which was added to the arrays class by JDK 8. 

static <T> Stream<T> stream(T[ ] array)

This method returns a sequential stream to the elements in array. For example, given an
array called addresses of type Address, the following obtains a stream to it:
 

Stream<Address> addrStrm = Arrays.stream(addresses); 

Lets start with a short example. We will use this data model in all examples:

Class Author{
String name;

int countOfBooks;
}
class Book{
String name;
int year;
Author author;
}
Let's imagine that we need to print all authors in a books collection who wrote a book after 2010. How would we do it in Java 7?

for(Book book:books){
if(book.author!=null&&book.year>2010)
{
System.out.println(book.author.name);
}
}

In Java 8 how would we do that same problem above:

books.stream().filter(book ->book.year>2010)
//filter out books published in or before 2010

.map(Book::getAuthor)//get the list of authors from the list

.map(Author::getName//get the list of names for remaining authors 

.forEach(System.out::println)//print the value of each remaining element

It is only one expression that is the method stream() on any Collection returns a Stream object encapsulating all the elements of that collection. This can be manipulated with different modifiers from the Stream API, such as filter() and map(). Each modifier returns a new Stream Object  with the results of the modification,which can be further manipulated. The forEach() method allows us to perform some action for each instance of the resulting stream.

The Stream API helps developers look at java collections from a new angle. Imagine now that we need to get a Map of available languages in each country. How would this be implemented in Java 7?

Map<String, Set<String>>CountryToSetOfLanguages=new HashMap<>();

for(Locale locale:Locale.getAvailableLocales())
{
String country=locale.getDisplayCountry();

if(!countryToSetOfLanguages.containsKey(country))
{
countryToSetOfLanguages.put(country,new HashSet<>());
}
countryToSetOfLanguages.get(country).add(locale.getDisplayLanguage());
}

In java 8 the above same will be rewritten below:

import java.util.stream.*;
import static java.util.stream.Collectors.*;
.........
........
Map<String, Set<String>>CountryToSetOfLanguages=Stream.of(Locale.getAvailableLocales()).collect(groupingBy(Locale::getDisplayCountry,mapping(
Locale::getDisplayLanguage,toSet())));

The method collect() allows us to collect the results of a stream in different ways. Here,we can see that it firstly groups by country,and then maps each group by language(groupinBy() and toSet() are both static methods from the Collectors class).




 

No comments:

Post a Comment

High Paying Jobs after Learning Python

Everyone knows Python is one of the most demand Programming Language. It is a computer programming language to build web applications and sc...