What is Stream in Java ?
Stream in Java is a sequence of elements on which operations can be performed. Stream operations can be intermediate
or terminal
. This definition sounds very similar to exisiting Collections.
What is difference between Collections and Streams
Collections is an in memory data structure which holds all the elements in the memory. In Stream the elements are computed on demand and the values are passed to next stream or returned. In Collection, the entire collection has to be computed to pass on to the next collection, whereas stream passes elements as it computes to the next Stream thus allowing Stream not to store the complete data set im memory.
Stream operations are terminal
or intermediate
and are combined to form stream pipelines. A stream pipeline consists of a source (such as a Collection, an array, a generator function, or an I/O channel); followed by zero or more intermediate operations such as Stream.filter
or Stream.map
and a terminal operation such as Stream.forEach
or Stream.reduce
. Terminal operations return a result of certain type and intermediate returns the Stream itself allowing to have multiple streams in a chain. Most of the stream operations take some kind of lambda expressions.
Types of Streams
Streams can be created from different sources and collections such as List and Set. The classes Stream, IntStream, LongStream, and DoubleStream are streams over objects and the primitive int, long and double types.
Streams can be generated:
Arrays.asList("a1", "a2", "a3")
.stream()
.forEach(System.out::println)
List l = new ArrayList() ;
l.stream()
.forEach(System.out::println)
Stream.of("a1", "a2", "a3")
.stream()
.forEach(System.out::println)
IntStream.range(1, 10)
.forEach(System.out::println);
Note: forEach
is a terminal function here
Mapping regular Stream
to primitive Stream.
Sometimes it's useful to transform a regular object stream to a primitive stream or vice versa.
Stream.of("1", "2", "3")
.mapToInt(Integer::parseInt)
.average()
.ifPresent(System.out::println);
IntStream.range(2013, 2016)
.mapToObj(i -> "Year " + i)
.forEach(System.out::println);
//Output
2.0
Year 2013
Year 2014
Year 2015
Stream Intermediate Functions
Intermediate functions returns the Stream itself, allowing to chain multiple such functions. Intermediate functions are lazily executed which means unless there is a terminal function append to Stream, the intermediate funciton will not be called. Some of commonly used functions:
As name suggests, it is used for filtering the elements from this stream which doesn't satisy a criteria.
IntStream.range(1,10)
.filter(num -> num%3 == 0)
.forEach(System.out::println);
Returns a stream consisting of the results of applying the given function to the elements of this stream
Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.forEach(System.out::println);
//Output
MON
TUES
WED
THUR
FRI
SAT
SUN
//using filter with map
Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.filter(s -> s.contains("T"))
.forEach(System.out::println);
//OUTPUT
TUES
THUR
SAT
One thing to note is that the ordering in which the functions are defined matter and execution takes place in the similar manner.Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
//Output
FRI
MON
SAT
SUN
THUR
TUES
WED
Stream Terminal Functions
Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.collect(Collectors.toList())
//to Set
Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.collect(Collectors.toSet())
Stream.of("mon", "tues", "wed", "thur", "fri", "sat", "sun")
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
//Output
FRI
MON
SAT
SUN
THUR
TUES
WED
boolean isPresent = IntStream.range(1,10)
.anyMatch(num -> num %3 == 0);
System.out.println(isPresent);
//Output
true
Predicate
.
int num = IntStream.range(4,10)
.filter(n -> n%3 ==0)
.findFirst()
.getAsInt();
//Output
6
Predicate
The behavior of the operation is nondeterministic. This is mainly used with parallel streams.
int num = IntStream.range(4,10)
.filter(n -> n%3 ==0)
.findAny()
.getAsInt();
//Output
6