Java 8 Streams

17 September 2014
By Gonçalo Marques
 
java java8
In this article we will cover Java 8 Streams.

Introduction

Java 8 introduced streams as way to perform functional operations over collections of elements, such as the traditional map-reduce transformations. In this article we will cover the most important features provided by Java 8 streams.

One important feature of streams is the kind of operations one may execute against them. There are two kinds of operations: intermediate and terminal. Intermediate operations return the modified stream to the caller so one may call additional operations over the stream in a nested way. Terminal operations return a result of a given type and one may not execute any other streaming operations over the result.

The following collection will be used across the entire article in order to cover the available Java stream operations:


Collection<Integer> integerCollection = new ArrayList<>();
integerCollection.add(1);
integerCollection.add(5);
integerCollection.add(4);
integerCollection.add(2);
integerCollection.add(3);
integerCollection.add(6);

Filter

The Filter operation allows one to execute a predicate against a stream of elements (more info about Predicates in the following article: Java 8 Predicates and Functions).

The following example filters the stream and prints only even integers:

Filtering and printing even integers

// Will print 4, 2, 6
integerCollection.stream().filter((i) -> i % 2 == 0).forEach(System.out::println);

Note that we called forEach after filter. This means that filter is an intermediate operation, ie. one may call additional operations over the filter operation result. The operation forEach is a terminal operation, ie. it produces a result and one may not call additional stream operations against the result.

Sorted

Sorted is another intermediate operation that will return an ordered view of the provided collection. Sorted operation sorts the collection over the natural order unless one provides a comparator:

Sorted operation

// Will print 3, 4, 5, 6
integerCollection.stream().filter((i) -> i > 2).sorted().forEach(System.out::println);

// Will print 6, 5, 4, 3
integerCollection.stream().filter((i) -> i > 2)
   .sorted((i1, i2) -> i2.compareTo(i1))
   .forEach(System.out::println);

Note: As we have said previously, sorted() will return a sorted view of the original collection. The original collection will not be modified.

Map

Map is also an intermediate operation that will convert each one of the stream elements into another element. The resulting elements may be of any arbitrary type:

Map operation

// Will print 1, 4, 9, 16, 25, 36
integerCollection.stream().sorted().map((i) -> i * i)
   .forEach(System.out::println);

// Will print
// Hello 1
// Hello 2
// Hello 3
// Hello 4
// Hello 5
// Hello 6
integerCollection.stream().sorted()
   .map((i) -> "Hello " + String.valueOf(i))
   .forEach(System.out::println);

Match

The match operation is a terminal operation that checks if a given condition - or predicate - matches against the stream. Match may be executed against a subset of the stream or against the entire stream.

Match operation

// Will print 1, 4, 9, 16, 25, 36
integerCollection.stream().sorted().map((i) -> i * i)
   .forEach(System.out::println);

// Will print false
System.out.println(integerCollection.stream().anyMatch((i) -> i > 10));

// Will print false
System.out.println(integerCollection.stream().anyMatch((i) -> i > 10));

// Will print true
System.out.println(integerCollection.stream().allMatch((i) -> i < 10));

// Will print true
System.out.println(integerCollection.stream().noneMatch((i) -> i > 6));

Since match is a terminal operation it will produce a result (in this case of type boolean) and one may not execute additional streaming operations over the result.

Count

Count is another terminal streaming operation that will count the number of elements in a stream.

Count operation

// Will print 3
System.out.println(integerCollection.stream().filter((i) -> i > 3)
   .count());

Reduce

Reduce is another terminal streaming operation that will - as the name states - reduce the stream elements and produce a result. The result if of type Optional (Java 8 Optional).

Reduce operation

Optional<Integer> result = integerCollection.stream()
   .filter((i) -> i > 3).reduce((i1, i2) -> i1 + i2);

// Will print 15
result.ifPresent(System.out::println);

Reference

Aggregate Operations (The Java Tutorials - Collections)

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: