Java Stream API tutorial

Java: back to basics.
Reading Time: 3 minutes

Java Stream API was one of the major features released with Java 8, that let you code in declarative style.

It supports function-style operations on streams of elements, such as map, filter and various other transformations.

Streams vs Collection

It is a myth that Java Stream API have replaced Collections in Java. Most of the collections are a main source for the stream to work on and they are often used together.

Some of the major difference between Streams and Collection are:


CollectionStream
StorageStorage of data. Collections are about data.No storage of data. Streams are about computations on data
Data ModificationCan add/remove elementsFunctional in nature. Operations on stream eg. filtering will result in a new Stream
IterationExternal iteration on Collections using loops
Perform iteration internally
TraversalCan be traversed multiple timesTraversable only once
EvaluationEager evaluation; All elements are computed in the beginning itselfLazy evaluation; Intermediate operations are not evaluated until terminal operation is invoked.

Creating a Stream

String[] arr = {"d", "b", "c"};
System.out.println("Sorted Stream: " + Stream.of(arr).sorted().collect(Collectors.toList()));

The above code snippet creates a Stream from using Stream.of() and sorts the stream in its natural order, returning a sorted list as output.

Stream Operations

Intermediate operations

Intermediate operations are the ones that return the stream itself. Some of them are:

filter()

It accepts a predicate to filter all elements of the stream. This operation acts as an intermediate by enabling us to call another stream operation on the result.

For example,

knolders.stream().filter((str) -> str.startsWith("K"))
 .forEach(System.out::println);

map()

map lets you convert the given element into another object.

knolders.stream().filter((str) -> str.startsWith("K"))
.map(String::toUpperCase)
.forEach(System.out::println);

Terminal Operations

Terminal operations return a result of a certain type instead of returning a Stream.

forEach()

It helps in iterating over all elements of a stream and perform some operation on the elements.

memberNames.forEach(System.out::println);

collect()

Collect is a useful terminal operation used  to transform the elements of the stream into a different kind of result, e.g. a List, Set or Map.

It accepts a Collector which consists of four different operations: a supplier, an accumulator, a combiner and a finisher.

Java 8 onwards supports various built-in collectors via the Collectors class.

List<String> namesInUppercase = knolders.stream().sorted()
  .map(String::toUpperCase)
 .collect(Collectors.toList());

reduce()

The reduction operation combines all elements of the stream into a single result.

Optional<String> reduced = knolders.stream()
.reduce((s1,s2) -> s1 + "@" + s2);
reduced.ifPresent(System.out::println);

                    

Short circuiting operations

Short-circuiting operations allow the computations on infinite streams to complete in finite time. Some of the short-citcuiting operations are:

limit() 

It limits the stream elements to process.

int [] arr = {1,2,3,4,5,6,7,8,9,11};
Arrays.stream(arr)
      .limit(5)
      .forEach(System.out::println);

findFirst(), findAny()

firstFist() returns the first element from the Stream.
findAny() returns any element from the Stream. It may be possible to get a different result every time with findAny() operation.

int [] arr = {1,2,3,4,5,6,7,8,9};
Integer findFirstElem = Arrays.stream(arr).filter(i -> (i%2) == 0)
.findFirst()
.orElse(-1);

Integer findAnyElem = Arrays.stream(arr).filter(i -> (i%2) == 0)
.findAny()
.orElse(-1);

allMatch(), anyMatch()

These short circuit operators returns true or false value depending on the condition being evaluated.
allMatch() evaluates the condition for all the steams and will return a boolean value.

anyMatch() evaluates the condition in the stream until it finds its match and once the match is found, It exits the processing and returns a boolean value.

int [] arr = {1,2,3,4,5,6,7,8,9,11};
System.out.println("All numbers are greater than -1 : " + Arrays.stream(arr).allMatch(i-> i > -1));

System.out.println("Contains any numbers greater than 10 : " + Arrays.stream(arr).anyMatch(i-> i > 10));

References

Written by 

Himani is a Software Consultant, having experience of more than 2.5 years. She is very dedicated, hardworking and focussed. She is Familiar with C#, C++, C , PHP, Scala and Java and has interest in Functional programming. She is very helpful and loves to share her knowledge. Her hobbies include reading books and cooking.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading