0% found this document useful (0 votes)
15 views33 pages

Java 8 Stream API Explained

This document provides a comprehensive guide to the Java 8 Stream API, detailing its creation, intermediate, and terminal operations through examples. It explains the concept of streams as sequences of elements for performing operations and covers various methods for creating streams, filtering, mapping, and collecting results. The article serves as a resource for understanding and utilizing the Stream API effectively in Java programming.

Uploaded by

san786m
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views33 pages

Java 8 Stream API Explained

This document provides a comprehensive guide to the Java 8 Stream API, detailing its creation, intermediate, and terminal operations through examples. It explains the concept of streams as sequences of elements for performing operations and covers various methods for creating streams, filtering, mapping, and collecting results. The article serves as a resource for understanding and utilizing the Stream API effectively in Java programming.

Uploaded by

san786m
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Java 8 Stream API - You Learn Code [Link]

com/java-8-stream-api/

JAVA SPRING BOOT  

JAVA SPRING BOOT  

JAVA 8 STREAM API


by geonikpal in Java

In this article, we’ll learn everything regarding Java Stream API that was introduced
in Java 8, through detailed examples.

1 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA
Table ofSPRING
ContentsBOOT  

1. What Is a Java Stream?


2. How to Create a Java Stream
2.1 [Link](T value), [Link](T… values) and [Link](T t)
2.2 [Link]()
2.3 [Link](Supplier s) and [Link]()
2.4 Creating a Java Stream From a Collection or Map
2.5 Stream iterate(final T seed, final UnaryOperator f) Example
2.6 Stream iterate(T seed, Predicate hasNext, UnaryOperator next) Example
2.7 Stream concat(Stream a, Stream b) Example
3. Intermediate Operations of Java 8 Stream API
3.1 Stream filter(Predicate predicate) Example
3.2 Stream map(Function mapper) example
3.3 Stream mapToInt, mapToLong and mapToDouble Functions Examples
3.4 Stream flatMap(Function mapper) Example
3.5 Stream flatMapToInt, flatMapToLong and flatMapToDouble Functions
Examples
3.6 Stream mapMulti(BiConsumer mapper) Example
3.7 Stream distinct() Example
3.7 Stream sorted() Example
3.8 Stream sorted(Comparator comparator) Example
3.9 Stream peek(Consumer action) Example
3.10 Stream limit(long maxSize) Example
3.11 Stream skip(long n) Example
3.12 Stream takeWhile(Predicate predicate)
3.13 Stream dropWhile(Predicate predicate)
4. Terminal Operations of Java 8 Stream API
4.1 Stream forEach(Consumer consumer) and forEachOrdered(Consumer
consumer) Examples
4.2 Stream Object[] to Array and A[] toArray(IntFunction generator) Examples
4.3 Stream Reduce Methods Examples
4.4 Stream toList() Example

2 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA SPRING
4.5 Stream BOOT
min(Comparator 
comparator) and max(Comparator comparator) 

Example
4.6 Stream count Example
4.7 Stream anyMatch(Predicate), allMatch(Predicate) and
noneMatch(Predicate) Examples
4.8 Stream findFirst() and findAny() Examples
4.9 Stream collect Methods
4.9.1 Stream R collect(Supplier supplier, BiConsumer accumulator, BiConsumer
combiner) Example
4.9.2 Stream R collect(Collector collector) Examples
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
[Link] [Link]() Example
5. A Visualization of Java 8 Stream
6. Conclusion
7. Sources

1. What Is a Java Stream?


You can think of a stream as a sequence of elements, that allows you to perform
sequential and parallel operations. Furthermore, you cannot add any elements once
the stream has been created nor you can retrieve an element by providing an index.

Streams have 2 kinds of operations:

1. Intermediate Operations: These operations will filter, modify and/or transform


the elements of the stream and then return the stream with the filtered/modified
/transformed elements. This allows you to continue performing operations that
Stream API provides.

3 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

2. Terminal Operations:
BOOT These operations will transform the stream into another 
JAVA SPRING 
primitive or object. After applying a terminal operation, you could have an int ,
long , String, Optional, any collection(such as List, Set), or even a Map.

An important characteristic of a stream is that once you have performed any of the
intermediate or terminal operations, you will be unable to perform more operations
unless you chain them. Consider the example below:

// Applying a terminal after an intermediate operation


Stream<String> stream = [Link]("hello");
[Link](String::toLowerCase);
[Link]([Link]::println);

The third line will produce the following exception:

Exception in thread "main" [Link]:


stream has already been operated upon or closed

To remedy this, you have to write the following:

stream
.map(String::toLowerCase)
.forEach([Link]::println);

Before we delve into streams, I suggest that you read the following articles as they
would help a lot in taking full advantage of the stream API.

▪ Java Lambda Expressions

▪ Functional Interface Java Tutorial

2. How to Create a Java Stream


There are multiple ways to create a stream. Let’s go through each of them:

2.1 [Link](T value), [Link](T… values) and


[Link](T t)
The first method allows only one value whereas the second allows multiple values.
Note that null values are not allowed but if you do want to initialize a stream with a

4 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

null
JAVA value, use [Link](T
you can BOOT
SPRING 
t) . 

Stream<String> stream = [Link]("Hello", "World");


Stream<Integer> streamInteger = [Link](5);
var s = [Link](null);

2.2 [Link]()
This method follows the builder pattern and it is a different way to create and fill a
stream. One difference with the previous way of creating a stream is that by using
builder, you are obliged to declare your stream as Stream<Object>.

Stream<Object> built = [Link]()


.add("Code")
.add("Learn")
.add("Hub")
.build();

2.3 [Link](Supplier s) and [Link]()


You can also generate a Stream by using [Link](Supplier s) . Let’s
see an example:

Stream<List<String>> streamStringGen = [Link](() -> {


List<String> list = new ArrayList<>();
[Link]("hello");
[Link]("world");
return list;
});

As you can observe, this stream now has one element; a list that has two strings. If
you want to convert it to a Stream<String> you would need to use flatMap()
which will see later how it works.

Finally, If you need an empty stream, you can use the [Link]() method.

2.4 Creating a Java Stream From a Collection or Map


The most common use case of streams is to convert for example a list, to a stream,
perform some operations, and then back to a list.

5 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

List<String> list = [Link]("C", "L", "H")


JAVA SPRING BOOT
.stream()  
.filter(l -> [Link]("C"))
.toList();
Set<String> set = [Link]("C", "L", "H")
.stream()
.filter(l -> [Link]("C"))
.collect([Link]());
Map<Long, String> map = [Link](1L, "C", 2L, "L", 3L, "H")
.entrySet()
.stream()
.filter(l -> [Link]().equals("C"))
.collect([Link]([Link]::getKey,
[Link]::getValue));

In the above examples, we used the stream() method the Collection interface has,
then filtered all the values that are equal to “C” and converted them back to the
original data structure.

2.5 Stream iterate(final T seed, final UnaryOperator f)


Example
This method allows you to declare a seed and use a UnaryOperator to produce the
new values. As you would expect, this leads to an infinite stream, so using limit()
is required unless you want to have errors.

So if you would like to create a stream and, print the all powers of two, from 20 to 219,
you could do it as shown below:

Stream
.iterate(1, i -> i * 2)
.limit(20).
forEach([Link]::println);

Furthermore, you could produce the first 10 Fibonacci numbers:

Stream
.iterate([Link](0, 1), fibList ->
[Link]([Link](1), [Link](0) +
[Link](1)
))
.limit(10)
.map(list -> [Link](0))

6 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.forEach([Link]::println);
JAVA SPRING BOOT  

2.6 Stream iterate(T seed, Predicate hasNext,


UnaryOperator next) Example
This works like the previous method, but now you can specify a predicate, that if it
fails, the iteration will stop.

So the below snippet will only print the numbers 1-10:

Stream
.iterate(1, i -> i < 10, i -> i + 1)
.limit(20)
.forEach([Link]::println);

2.7 Stream concat(Stream a, Stream b) Example


With stream concat() you can combine 2 streams into one as shown below:

Stream<String> clh = [Link]("Code", "Learn", "Hub");


Stream<String> programmingLanguages = [Link]("Java", "SQL",
"Swift", "Python");

Stream
.concat(clh, programmingLanguages)
.forEach([Link]::println);

3. Intermediate Operations of Java 8 Stream API


As it has already been stated, intermediate operations are all methods that will return
a stream. We’ll go through each of them in the following sections.

In order to make our examples more interesting, consider that we have created the
following setup:

private record Car(long id, String brand, String model, int


horsePower, double price){};

private static List<Car> cars = [Link](


new Car(1, "Opel", "Astra", 105, 20_000),
new Car(2, "Lamborghini", "Gallardo", 320, 120_000),

7 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

new Car(3, "Mercedes", "C180", 200, 40_000),


JAVA SPRING BOOT
new Car(4, "Opel", "Insignia", 120, 28_000), 
new Car(5, "VW", "Polo", 92, 17_000),
new Car(6, "BMW", "M3", 250, 80_000)
);

3.1 Stream filter(Predicate predicate) Example


The predicate is just a simple function that accepts one parameter of any type and
returns true or false .

The filter() method allows you to filter only the elements of the stream that match
this predicate.

Below you can find an example where we filter only the cars that cost more than
$30,000.

cars
.stream()
.filter(car -> [Link]() > 30_000)
.forEach([Link]::println);

After we filter, we print every element that currently exists in the stream using
forEach(Consumer consumer) . The output is the following:

Car[id=2, brand=Lamborghini, model=Gallardo, horsePower=320,


price=120000.0]
Car[id=3, brand=Mercedes, model=C180, horsePower=200, price=40000.0]
Car[id=6, brand=BMW, model=M3, horsePower=250, price=80000.0]

If you want to learn more about how filter() works, check this article.

3.2 Stream map(Function mapper) example


The function is just a simple function that accepts one parameter and returns a value.

The map() method allows you to transform all the elements of the stream to any
type that you might need.

Below you can find an example where we convert the car objects to simple strings
that contain the model of each car.

8 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

cars
[Link]()
SPRING BOOT  
.map(Car::model)
.forEach([Link]::println);

Here we used a method reference that is equivalent to the following lambda


expression:

car -> [Link]()

The output is the following:

Gallardo
C180
Insignia
Polo
M3

If you want to learn more about how map() works, check this article.

3.3 Stream mapToInt, mapToLong and mapToDouble


Functions Examples
These functions convert the elements of the stream to the respective type ( int ,
long , double ) while at the same time, your stream will no longer be a stream
but a IntStream , LongStream or DoubleStream . As a result, you will be able to
use all the extra methods that might be provided by each interface.

Let’s see some examples:

Example of getting the average horsePower, using mapToInt :

cars
.stream()
.mapToInt(Car::horsePower).average();

Note that average() and sum() are both terminal methods.

Example of getting the sum of cars‘ prices using mapToDouble :

cars

9 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.stream()
[Link](Car::price).sum();
SPRING BOOT  

3.4 Stream flatMap(Function mapper) Example


This method is a little bit different than map() , as the mapper must return a stream. It
is used to make deep data structures linear, consider the following list of lists:

List<List<String>> brands = new ArrayList<>();


[Link]([Link]("Ferrari", "Lamborghini", "Maserati"));
[Link]([Link]("Opel", "VW", "Fiat"));
[Link]([Link]("BMW", "Mercedes", "Audi"));

As you can observe, each list has some brands, let’s say we have a task to convert
this to a simple List<String> . How would we do that? Here comes flatMap into
play:

List<String> brandsFlat = brands


.stream()
.flatMap(Collection::stream)
.toList();

Collection::stream is a method reference that is equivalent to the lambda


expression brandsList -> [Link]() .

As a result, our list will now contain just strings and not a list of strings.

3.5 Stream flatMapToInt, flatMapToLong and


flatMapToDouble Functions Examples
As with section 3.3, the difference between these methods and flatMap() is that
they return an IntStream , LongStream , or DoubleStream .

Let’s say we have a list containing a list of cars:

List<List<Car>> carsDeepList = new ArrayList<>();


[Link](cars);
[Link](
[Link](
new Car(7L, "Opel", "Zafira", 100, 20_000))
);

10 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

[Link](
JAVA SPRING BOOT 
[Link]( 
new Car(8L, "Opel", "Corsa", 80, 18_000))
);

The first addition is the car list we have mentioned in section 3.

Now let’s say that your task is to find the max price of all cars inside the
carsDeepList , you can do it as shown below:

double brandsFlat = carsDeepList


.stream()
.flatMapToDouble(carsList ->
[Link]().mapToDouble(Car::price))
.max()
.orElse(-1);

[Link](brandsFlat);

The result will be 120000.0 .

3.6 Stream mapMulti(BiConsumer mapper) Example


This method was added in Java 16 and it accepts a BiConsumer . This BiConsumer
accepts 2 parameters, the element and a consumer which will be used to produce
the new values.

As per Javadocs, this method is similar to flatMap() but it should be preferred in


these two cases:

▪ When we like to replace each element of the stream with a very small number of
elements, since we would avoid creating a new stream like flatMap() does.

▪ When it is easier to use a consumer than returning the elements as a stream

Consider an example that falls to the first reason why we might opt for mapMulti
instead of flatMap .

[Link]().<Map<String, String>>mapMulti(
((carsList, consumer) -> {
for(Car car: carsList){
if([Link]() < 0.05){

11 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

[Link](
JAVA SPRING BOOT  [Link]([Link](), [Link]()) 
);
}
}
}
));

This will convert a list of lists of cars to a list of maps with the model as a key and the
brand as value, with a 5% probability.

Finally, there are primitive versions of these methods ( mapMultiToInt ,


mapMultiToLong , and mapMultiToDouble ) which work like mapMulti but return an
IntStream , LongStream , and DoubleStream respectively.

3.7 Stream distinct() Example


Stream distinct() removes any duplicate elements that might exist in the stream. The
decision on whether two objects are the same is based on the result of equals()
method. Let’s jump to an example:

[Link](new Car(1, "Opel", "Astra", 105, 20_000),


new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "Mercedes", "C180", 200, 40_000))
.distinct()
.forEach([Link]::println);

As you would expect, the result would be to print 4 cars in total instead of 5. Note that
the 5th element has a different id so it is considered a different object. Hence,
equals() would return false when compared to any other element.

3.7 Stream sorted() Example


This method returns the stream sorted according to the natural order. Note that to
apply this function, your objects inside the stream must implement comparable,
otherwise, a ClassCastException will be thrown. Let’s see some examples:

//Will print them in ascending order


[Link](1, -1, 5, 100, 3, 0)

12 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.sorted().forEach([Link]::println);
JAVA SPRING BOOT  
//Will print them in ascending lexicographical order
[Link]("Code", "Learn", "Hub", "Hello", "World")
.sorted().forEach([Link]::println);
//Will fail as Car object does not implement comparable interface
try {
[Link](new Car(1, "Opel", "Astra", 105, 20_000),
new Car(2, "Lamborghini", "Gallardo", 320,
120_000),
new Car(3, "Mercedes", "C180", 200, 40_000))
.sorted()
.forEach([Link]::println);
} catch (Exception e){
[Link]();
}

As expected, the following will print:

-1
0
1
3
5
100
Code
Hello
Hub
Learn
World
[Link]: class StreamExamples$Car cannot be cast
to class [Link] (StreamExamples$Car is in unnamed module
of loader 'app'; [Link] is in module [Link] of loader
'bootstrap')

Now, if for example, you wanted to sort the cars by ascending price, you could
change the record as follows:

private record CarComparable(long id, String brand, String model, int


horsePower, double price) implements Comparable<CarComparable>{
@Override
public int compareTo(CarComparable o) {
double priceDif = [Link] - [Link];
if(priceDif > 0){
return 1;
} else if(priceDif == 0){

13 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

return 0;
JAVA SPRING
} else BOOT
{  
return -1;
}
}
};

Then if you run the following code:

[Link](new CarComparable(1, "Opel", "Astra", 105, 20_000),


new CarComparable(2, "Lamborghini", "Gallardo", 320,
120_000),
new CarComparable(3, "Mercedes", "C180", 200,
40_000))
.sorted()
.forEach([Link]::println);

The output would be:

CarComparable[id=1, brand=Opel, model=Astra, horsePower=105,


price=20000.0]
CarComparable[id=3, brand=Mercedes, model=C180, horsePower=200,
price=40000.0]
CarComparable[id=2, brand=Lamborghini, model=Gallardo,
horsePower=320, price=120000.0]

3.8 Stream sorted(Comparator comparator) Example


This method is just like the previous one but is a lot more flexible since you can pass
an inline comparator to choose the sorting rule you might like to use.

Let’s say you’d like cars to be sorted in descending order by the following criteria:

1. price
2. horsePower
3. brand

To achieve that, it would be simple as that:

[Link]( new Car(1, "Opel", "Astra", 105, 20_000),


new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),

14 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

new Car(4, "BMW", "Z4", 180, 40_000),


JAVA SPRING BOOT
new Car(5, "Opel", "Mokka", 180, 40_000) 
)
.sorted(Comparator
.comparing(Car::price)
.thenComparing(Car::horsePower)
.thenComparing(Car::brand)
.reversed()
)
.forEach([Link]::println);

And the output would be:

Car[id=2, brand=Lamborghini, model=Gallardo, horsePower=320,


price=120000.0]
Car[id=3, brand=Mercedes, model=C180, horsePower=200, price=40000.0]
Car[id=5, brand=Opel, model=Mokka, horsePower=180, price=40000.0]
Car[id=4, brand=BMW, model=Z4, horsePower=180, price=40000.0]
Car[id=1, brand=Opel, model=Astra, horsePower=105, price=20000.0]

3.9 Stream peek(Consumer action) Example


Stream peek is mainly used for debugging, and as can you infer from its name, you
can peek at the state of the stream in order. Additionally, you can use it like forEach
which is void , in order to transform the state of the elements and then continue
using the stream.

Note that since stream operations are lazy, they won’t be run until you collect the
result.

Consider the example below:

List<String> models = [Link]( new Car(1, "Opel", "Astra",


105, 20_000),
new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "BMW", "Z4", 180, 40_000),
new Car(5, "Opel", "Mokka", 180, 40_000)
)
.filter(car -> [Link]().equals("Opel"))
.peek(car -> [Link]("Filtered car:" + car))
.map(Car::model)
.peek(model-> [Link]("Mapped car object to
model:" + model))

15 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.toList();
JAVA SPRING BOOT  

The output will be the following:

Filtered car:Car[id=1, brand=Opel, model=Astra, horsePower=105,


price=20000.0]
Mapped car object to model:Astra
Filtered car:Car[id=5, brand=Opel, model=Mokka, horsePower=180,
price=40000.0]
Mapped car object to brand:Mokka

3.10 Stream limit(long maxSize) Example


This method is pretty simple as it allows only maxSize number of elements in the
stream, for example, the following:

[Link]( new Car(1, "Opel", "Astra", 105, 20_000),


new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "BMW", "Z4", 180, 40_000),
new Car(5, "Opel", "Mokka", 180, 40_000)
)
.limit(2).forEach([Link]::println);

This will print only the first two elements as the other 3 will be truncated from the
stream.

3.11 Stream skip(long n) Example


Stream skip will just ignore the first n elements and only hold the rest of them so the
snippet below:

[Link]( new Car(1, "Opel", "Astra", 105, 20_000),


new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "BMW", "Z4", 180, 40_000),
new Car(5, "Opel", "Mokka", 180, 40_000)
)
.skip(4)
.forEach([Link]::println);

This will print:

16 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

Car[id=5, brand=Opel, model=Mokka, horsePower=180, price=40000.0]


JAVA SPRING BOOT  

3.12 Stream takeWhile(Predicate predicate)


Stream takeWhile was introduced in Java 9 and it acts differently depending on
whether the stream is ordered or unordered:

For ordered streams, it just filters the elements while the predicate returns
true . If at some point the predicate returns false for an element, this and the
rest of the elements will be filtered out. Let’s jump to an example:

[Link]( new Car(1, "Lamborghini", "Gallardo", 320, 120_000),


new Car(2, "Opel", "Astra", 105, 20_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "BMW", "Z4", 180, 40_000),
new Car(5, "Opel", "Mokka", 180, 40_000)
)
.takeWhile(car -> [Link]() >= 40_000)
.forEach([Link]::println);

So here, the Opel Astra will fail the predicate, and even though the rest of the cars do
have price >= $40,000 , the output will be just Car[id=1, brand=Lamborghini,
model=Gallardo, horsePower=320, price=120000.0]

When it comes to unordered streams, the behavior is non-deterministic as it can


take any subset of the given elements that match the predicate.

3.13 Stream dropWhile(Predicate predicate)


This method does exactly the opposite of takeWhile , it drops the elements if they
match the predicate, and as soon as one element fails the predicate, the rest will be
kept in the stream regardless of the predicate result.

So the following snippet:

[Link]( new Car(1, "Lamborghini", "Gallardo", 320, 120_000),


new Car(2, "Opel", "Astra", 105, 20_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "BMW", "Z4", 180, 40_000),
new Car(5, "Opel", "Mokka", 180, 40_000)
)

17 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.dropWhile(car -> [Link]() > 20_000)


JAVA SPRING BOOT 
.forEach([Link]::println); 

Will lead to a stream without the Lamborghini Gallardo.

4. Terminal Operations of Java 8 Stream API


Terminal operations will lead to an object or primitive that is not of Stream type. As a
result, after applying a terminal operation, you won’t be able to use any of the
methods of section 3 without extra steps (e.g. using the stream() method to retrieve
a stream from a list or set).

In the following sections, we’ll see all terminal operations provided by stream API.

4.1 Stream forEach(Consumer consumer) and


forEachOrdered(Consumer consumer) Examples
The method forEach is void and performs actions on a stream. The difference with
forEachOrdered is noticeable only when using parallel streams as the result will be
always the same when it comes to forEachOrdered , whereas with forEach it may
vary.

[Link]("Using forEach in simple stream:");


[Link]("C", "L", "H").forEach([Link]::println);

[Link]("Using forEach in parallel stream:");


[Link]("C", "L", "H").parallel().forEach([Link]::println);

[Link]("Using forEachOrdered in parallel stream:");


[Link]("C", "L",
"H").parallel().forEachOrdered([Link]::println);

An example of an output of the above would be:

Using forEach in simple stream:


C
L
H
Using forEach in parallel stream:
L
H

18 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

C
JAVA SPRING BOOT in parallel
Using forEachOrdered  stream: 
C
L
H

Moreover, you can perform actions inside forEach , consider a simple Car POJO like
the record we had in the previous sections, and let’s say we would like to increase
the prices of some cars due to inflation:

List<CarPojo> carPojoList = [Link]( new


CarPojo("Lamborghini", "Gallardo", 320, 120_000),
new CarPojo("Opel", "Astra", 105, 20_000),
new CarPojo("Mercedes", "C180", 200, 40_000),
new CarPojo("BMW", "Z4", 180, 40_000),
new CarPojo("Opel", "Mokka", 180, 40_000)
);

carPojoList
.stream()
.forEach(carPojo -> {
switch ([Link]()){
case "Opel" -> [Link]([Link]() *
1.1);
case "Mercedes", "BMW" ->
[Link]([Link]() * 1.2);
case "Lamborghini" ->
[Link]([Link]() * 1.4);
}
});

[Link]([Link]::println);

After these operations, the result to be printed will have the updated prices:

CarPojo{brand='Lamborghini', model='Gallardo', horsePower=320,


price=168000.0}
CarPojo{brand='Opel', model='Astra', horsePower=105, price=22000.0}
CarPojo{brand='Mercedes', model='C180', horsePower=200,
price=48000.0}
CarPojo{brand='BMW', model='Z4', horsePower=180, price=48000.0}
CarPojo{brand='Opel', model='Mokka', horsePower=180, price=44000.0}

4.2 Stream Object[] to Array and A[] toArray(IntFunction

19 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

generator)
JAVA SPRINGExamples
BOOT  

You can use these two methods to convert a stream to an array. Note that the first
one will return an array of type Object while the second one whatever type you
might specify.

Object[] strings = [Link]("C", "L", "H")


.toArray();

String[] stringsArr = [Link]("C", "L", "H")


.toArray(String[]::new);

4.3 Stream Reduce Methods Examples


Reduce methods are used to reduce elements to a simpler value. As reduction
methods are quite complex, we’ll just demonstrate some simple examples. If you like
to dig in deeper, you can check Java Stream Reduce Tutorial.

Consider the examples below:

//simple reduce without initial value


List<Integer> numbers = [Link](1, 2, 3, 4, 5);
int sum = [Link]().reduce(Integer::sum).get();
[Link](sum);
// reduce with initial value
int sumWithSeed = [Link]().reduce(100,Integer::sum);
[Link](sumWithSeed);
// reduce with initial value and a combiner, allows you to change
return value
List<Integer> clh = [Link](1, 2, 3);
String result = [Link]()
.reduce("String is: ",
(firstNumber, secondNumber) -> firstNumber +
secondNumber,
String::concat
);
[Link](result);

The first version just uses a BinaryOperator to combine the values and produce a
result. Note that this version returns an Optional.

The second version works like the first, but it uses a value to start with instead of the

20 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

default
JAVA (e.g. for double the default would be 0.0.). 
SPRING BOOT 

The third version allows you to change the produced result by using a BiFunction
and a BinaryOperator .

4.4 Stream toList() Example


This method was added in Java 16 and it can replace the method
collect([Link]()) that was previously used.

However, if we dig deeper and use a debugger, we’ll see that the List produced by
Collectors class will be shown as ArrayList while the List produced by
toList() will be shown as [Link] which is unmodifiable.

Indeed, if you try to run the following snippet:

List<String> listCollectors = [Link]("C", "L",


"H").collect([Link]());
List<String> list = [Link]("C", "L", "H").toList();
[Link]("A");
[Link]("A");

You will get:

Exception in thread "main" [Link]

In the second addition where toList() was used.

4.5 Stream min(Comparator comparator) and


max(Comparator comparator) Example
Both of these methods accept a comparator which will determine the criteria for
which an object is considered bigger than the other. Both will return an Optional
which will contain the maximum or minimum element, otherwise an empty Optional
if the stream is empty. Additionally, if 2 maximums are found, one will be returned.

Let’s see an example where we find the cheapest and the most expensive car:

List<Car> list = [Link](

21 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

new Car(1L,"Lamborghini", "Gallardo", 320, 120_000),


JAVA SPRING BOOT"Opel", "Astra", 105, 20_000),
new Car(2L, 
new Car(3L, "Mercedes", "C180", 200, 40_000),
new Car(4L, "BMW", "Z4", 180, 40_000),
new Car(5L, "Opel", "Mokka", 180, 40_000)
);

Car expensive =
[Link]().max([Link](Car::price)).orElse(null);
Car cheap =
[Link]().min([Link](Car::price)).orElse(null);
[Link]("Most expensive car is: "+expensive);
[Link]("Cheapest car is: "+cheap);

The output will be:

Most expensive car is: Car[id=1, brand=Lamborghini, model=Gallardo,


horsePower=320, price=120000.0]
Cheapest car is: Car[id=2, brand=Opel, model=Astra, horsePower=105,
price=20000.0]

4.6 Stream count Example


Stream count will return a long value equivalent to the total elements that this
stream has.

List<Car> list = [Link](


new Car(1L,"Lamborghini", "Gallardo", 320, 120_000),
new Car(2L, "Opel", "Astra", 105, 20_000),
new Car(3L, "Mercedes", "C180", 200, 40_000),
new Car(4L, "BMW", "Z4", 180, 40_000),
new Car(5L, "Opel", "Mokka", 180, 40_000)
);

[Link]([Link]().count()); // Will print 5

4.7 Stream anyMatch(Predicate), allMatch(Predicate) and


noneMatch(Predicate) Examples
All of these methods accept a Predicate and return a boolean:

▪ anyMatch() will return true if at least one element matches the predicate.

22 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

▪ allMSPRING
JAVA atch() will
BOOTreturn tru
e if all elements match the predicate. 
▪ noneMatch() will return true if none of the elements match the predicate.

Below you can find some examples:

List<Car> list = [Link](


new Car(1L,"Lamborghini", "Gallardo", 320, 120_000),
new Car(2L, "Opel", "Astra", 105, 20_000),
new Car(3L, "Mercedes", "C180", 200, 40_000),
new Car(4L, "BMW", "Z4", 180, 40_000),
new Car(5L, "Opel", "Mokka", 180, 40_000)
);

boolean allHavePriceLessThan150k = list


.stream().
allMatch(car -> [Link]() < 150_000); //true

boolean atLeastOneIsLamborghini = list


.stream()
.anyMatch(car -> [Link]().equals("Lamborghini")); //true

boolean noneIsFerrari = list


.stream()
.noneMatch(car -> [Link]().equals("Ferrari")); //true

4.8 Stream findFirst() and findAny() Examples


Both methods return an Optional , since the stream could be empty.

▪ findFirst() will return the first element.

▪ findAny() is non-deterministic (it won’t produce the same result each time
is run) and it is mainly used to maximize performance in parallel
operations.

Finally, you can notice the difference when using parallel streams as shown below:

var any = [Link]("C", "L", "H")


.parallel()
.findAny()
.orElse(null);

var first = [Link]("C", "L", "H")

23 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

.parallel()
JAVA SPRING BOOT
.findFirst()  
.orElse(null);

[Link](any);
[Link](first);

In this case, the result will be "LC" .

4.9 Stream collect Methods


Stream collect methods are used to convert the stream to another object or data
structure. Stream API provides two collect methods:

▪ R collect(Supplier supplier,BiConsumer accumulator,BiConsumer


combiner) , which does not use the Collectors class.

▪ <R, A> R collect(Collector<? super T, A, R> collector), which accepts a collector


that we can create by calling methods of Collectors class.

4.9.1 Stream R collect(Supplier supplier, BiConsumer accumulator,


BiConsumer combiner) Example
This method accepts 3 parameters:

▪ A Supplier , which is used to choose the object or the data structure that our
stream will be converted to.

▪ A BiConsumer , which is the accumulator i.e. the operation that will be applied in
order to fill the object or data structure (the first parameter will be the DS and the
second the element to be added).

▪ A BiConsumer , which is the combiner i.e. the operation that we will use to
combine all the values produced by the accumulator.

Consider the example below where we convert a stream of cars to a Map of Ids as
keys and models as values:

Map<Long, String> carMap = [Link](


new Car(1L,"Lamborghini", "Gallardo", 320, 120_000),
new Car(2L, "Opel", "Astra", 105, 20_000),

24 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

new Car(3L, "Mercedes", "C180", 200, 40_000),


JAVA SPRING BOOT"BMW", "Z4", 180, 40_000),
new Car(4L, 
new Car(5L, "Opel", "Mokka", 180, 40_000)
).collect(
HashMap::new,
(map, car) -> [Link]([Link](), [Link]()),
HashMap::putAll
);

Of course, you can do the same with any data structure or even a StringBuilder
as shown below:

String combined = [Link]("Code", "Learn", "Hub", "is", "the",


"best.")
.collect(StringBuilder::new,
(sb, aString) -> [Link](aString).append(" "),
StringBuilder::append
).toString();
[Link](combined);

The output will be:

Code Learn Hub is the best.

4.9.2 Stream R collect(Collector collector) Examples


This method accepts a collector which you can retrieve by using methods of the
Collectors class.

Some of the most used methods are the following:

▪ [Link]() , which allows you to convert your stream to a map.


Should you like to learn about collectors to Map in-depth, take a look at our
Collectors to Map in Java article.

▪ [Link]() , which converts the stream to a list and more specifically


an ArrayList (We already saw an example back in section 4.4).

▪ [Link]() , which converts the stream to a set and more specifically


a HashSet.

▪ [Link] (), which allows you to specify exactly which


implementation of the Set or List interface you want.

25 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

▪ [Link]
JAVA SPRING BOOT (), which

converts a stream of string to a string. 

And many more aggregate functions that will not be analyzed in-depth in this article.

Before we begin, consider that we have the following list of cars:

List<Car> cars = [Link](


new Car(1, "Opel", "Astra", 105, 20_000),
new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "Opel", "Insignia", 120, 28_000),
new Car(5, "VW", "Polo", 92, 17_000),
new Car(6, "BMW", "M3", 250, 80_000)
);

Now we’ll see some self-explanatory examples of various methods provided by


Collectors class.

[Link] [Link]() Example


//Map cars to models and collect them to a list
List<String> models = cars
.stream()
.map(Car::model)
.collect([Link]());

[Link] [Link]() Example


//Map cars to brands and convert them to set, will remove duplicates
Set<String> brandsSet = cars
.stream()
.map(Car::brand)
.collect([Link]());

[Link] [Link]() Example


// Use toCollection to produce a LinkedHashSet with brands
LinkedHashSet<String> brandsLinkedHashSet = cars
.stream()
.map(Car::brand)
.collect([Link](LinkedHashSet::new));

[Link] [Link]() Example


// Use joining to reduce strings to one string

26 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

String brandsString = cars


JAVA SPRING BOOT
.stream()  
.map(Car::brand)
.distinct()
.collect([Link](","));
// Will print Opel,Lamborghini,Mercedes,VW,BMW

[Link] [Link]() Example


//Get average price
double averagePrice = cars
.stream()
.collect([Link](Car::price));

[Link] [Link]() Example


// Filter all the cars that cost > $50k
List<Car> carsMoreThan50k = cars
.stream()
.collect(
[Link](
car -> [Link]() > 50_000,
[Link]())
);

[Link] [Link]() Example


// Group cars by brand
Map<String, List<Car>> carsGroup = cars
.stream()
.collect(
[Link](
Car::brand,
[Link]()
)
);

[Link] [Link]() Example


//Create two partions, one with cars <=50k price and one with >50k
price
Map<Boolean, List<Car>> carsPartitionByPrice = cars
.stream()
.collect([Link](car -> [Link]() >
50_000));

27 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

5. A Visualization
JAVA SPRING BOOT of Java 8 Stream 

List<Car> cars = [Link](


new Car(1, "Opel", "Astra", 105, 20_000),
new Car(2, "Lamborghini", "Gallardo", 320, 120_000),
new Car(3, "Mercedes", "C180", 200, 40_000),
new Car(4, "Opel", "Insignia", 120, 28_000),
new Car(5, "VW", "Polo", 92, 17_000),
new Car(6, "BMW", "M3", 250, 80_000)
);

String[] modelsArray = [Link]()


.filter(car -> [Link]() > 50_000)
.sorted([Link](Car::price).reversed())
.map(Car::model)
.toArray(String[]::new);

We can use the stream trace provided by Intellij IDEA to visualize the following
stream processing and see how the magic happens:

Figure 1 – Stream Trace from Intellij IDEA

6. Conclusion
By now, you should have a good grasp of how streams work in Java and how to take
full advantage of all the methods offered by Java Stream API. You can find the
source code on our GitHub page.

7. Sources

28 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

[1]: Stream(Java
SPRINGSEBOOT
12 & JDK 12 – Oracle 
JAVA 

Tags: core java java java stream filter java stream map java stream reduce streams

PREVIOUS POST NEXT POST

@CONFIGURATIONPROPERTIES JAVA LINKEDLIST


ANNOTATION IN SPRING BOOT

geonikpal

 

Related Posts

29 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA SPRING BOOT  

D ATA S T R U C T U R E S &
J AVA J AVA ALGORITHMS

Java Classes & Objects How to Use the Java Break How to Implement the
Statement to Your Singleton Design Pattern in
Advantage Java

J AVA J AVA J AVA

Java Queue Java Stack Exception Handling in Java


– How to Use Try, Catch,
Finally, Throw and Throws
Keywords

J AVA J AVA

Java Set Java Sealed Class &


Interface

LOAD MORE

30 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA SPRING BOOT  

31 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA SPRING BOOT  

32 of 33 29/03/23, 8:13 pm
Java 8 Stream API - You Learn Code [Link]

JAVA SPRING BOOT  

You Learn Code and all content copyright © 2022-2023 Contact / Privacy Policy / Terms and Conditions

DISCLAIMER:

All trademarks and registered trademarks appearing on You Learn Code are the property of their respective owners.

Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. You Learn

Code is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

33 of 33 29/03/23, 8:13 pm

You might also like