Streams: Concepts
Streams: Concepts
Concepts
Stream
Intermediate Operations
filter()
map()
sorted()
distinct()
Terminal Operations
forEach()
count()
collect()
anyMatch()
allMatch()
noneMatch()
Introduction
In the course, we have learned different data structures likes, arrays, sets, etc. To
perform some operations on these data, we will iterate over the data and perform
operations on the original data. Java provides a way for processing data in a safer
and concise way through Streams.
1. Stream
It's important to note that a stream does not store the elements of an array, etc, it
simply provides a way to access them.
It means that we can perform operations on a stream without modifying the original
data.
Java consists of a
Stream interface from the java.util.stream package consists of all the methods
used to perform operations on streams.
int , long , and double . To use the Stream interface with primitive types,
we must use the wrapper classes Integer , Long , and Double , respectively.
The
Stream interface consists of a static and default method empty() that can
be used to create an empty stream.
Syntax
JAVA
1 Stream.empty();
Here,
1 import java.util.stream.Stream;
2
3 class Main {
4 public static void main(String[] arg
5 Stream<String> stream = Stream.e
6 }
7 }
In the above code, we have created an empty stream using the default method
Syntax
JAVA
1 collection.stream()
The
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Stream;
3
4 class Main {
5 public static void main(String[] ar
6 List<Integer> numbers = Arrays
7
7
8 Stream<Integer> numStream = num
9 }
10 }
Integer s and assigned it to numbers variable. We can notice that the type of
numbers is mentioned as List . The interfaces cannot be instantiated but can be
used for referencing. Hence, the above code executes successfully.
Syntax
JAVA
1 Stream.of(list of elements);
Code
JAVA
1 import java.util.stream.Stream;
2
3 class Main {
4 public static void main(String[] arg
5 Stream<Integer> stream = Stream
6 }
7 }
2. Working with Streams
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Stream;
3
4 class Main {
5 public static void main(String[]
6 List<Integer> numbers = Array
7
8 Stream<Integer> numStream =
9 Stream<Integer> filteredStre
10 filteredStream.forEach(n -> S
11 }
Expand
Output
2
4
The above code creates a stream of the list provided, filters the even numbers, and
displays each even number in a new line on the console.
We'll learn more about
filter() and forEach() methods later in this unit.
On every stream we can perform only one operation. After every operation the
stream is consumed/closed.
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Stream;
3
4 class Main {
5 public static void main(String[]
6 List<Integer> numbers = Array
7
8 Stream<Integer> numStream =
9 Stream<Integer> filteredStre
10 Stream<Integer> filteredStre
11 }
Expand
Output
1 streamSource.intermediateOperation().ter
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream() // stream so
8 .filter(eachName -> eac
9 .forEach(name -> System
10 }
11 }
Expand
Output
Alice
Charlie
In the above code, we have created a stream of strings, filtered the names that have
more than 4 letters and displayed the resultant names on the console. We have
written all these operations in a single statement.
3. Intermediate Operations
let's learn some of the commonly used methods to perform intermediate operations
on streams:
1. filter()
2. map()
3. sorted()
4. distinct()
1. filter()
The
It accepts a
Syntax
JAVA
1 stream.filter(Predicate)
Code
JAVA
1 import java.util.*;
2 import java.util.function.Predicate;
3
4 class Main {
5 public static void main(String[]
6 List<String> names = Arrays.
7
8 Predicate<String> predi = (e
9
10 names.stream() // stream so
11 .filter(predi) // inte
Expand
Output
Alice
Charlie
In the above code, we have created a stream of strings, filtered the names that have
more than 4 letters and displayed the resultant names on the console.
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream() // stream so
8 .filter(eachName -> eac
9 .forEach(name -> System
10 }
11 }
Expand
Output
Alice
Charlie
In the above code, the Java compiler recognizes that the lambda expression
2. map()
The
It accepts a
Syntax
JAVA
1 stream.map(Function)
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<Integer> numbers = Array
6
7 numbers.stream() // stream
8 .map(eachNumber -> ea
9 .forEach(number -> Sy
10 }
11 }
Expand
Output
4
10
12
2
In the above code, the Java compiler recognizes that the lambda expression
eachNumber -> eachNumber * 2 is being used to implement the Function
interface.
3. sorted()
The
sorted() method is used to sort the elements of the stream in ascending order.
Syntax
JAVA
1 stream.sorted()
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<Integer> numbers = Array
6
7 numbers.stream() // stream
8 .sorted() // intermed
9 .forEach(number -> Sy
10 }
11 }
Expand
Output
1
2
5
6
In the above code, the
sorted() method has arranged the elements of the numbers stream in ascending
order and returned a new stream. On the new stream, we have performed a terminal
operation using the forEach() method and displayed the sorted numbers on the
console.
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream() // stream so
8 .sorted() // intermedi
9 .forEach(name -> System
10 }
11 }
Expand
Output
Alice
Dave
bob
charlie
sorted() method has arranged the elements of the numbers stream in ascending
order based on the Unicode values of the characters in the string and returned a new
stream. On the new stream, we have performed a terminal operation using the
forEach() method and displayed the sorted strings on the console.
3.1 sorted(Comparator)
The
sorted() method also accepts Comparator (a functional interface) type as an
argument and returns a stream of the sorted elements based on the specified
operation.
Syntax
JAVA
1 stream.sorted(Comparator)
Example 1:
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<Integer> numbers = Array
6
7 numbers.stream()
8 .sorted((num1, num2)
9 .forEach(number -> Sy
10 }
11 }
Expand
Output
6
5
2
1
In the above code, the Java compiler recognizes that the lambda expression
(num1, num2) -> num2 - num1 is being used to implement the Comparator
interface.
The lambda expression used in the above code calculates the difference
num2 - num1 which results in a positive number if num2 > num1 , a
negative number if num1 > num2 , and zero if num2 == num1 . The
sorted() method internally sorts the numbers based on these results and returns a
stream containing the numbers in descending order.
Example 2:
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<Integer> numbers = Array
6
7 numbers.stream()
8 .sorted(Comparator.rev
9 .forEach(number -> Sy
10 }
11 }
Expand
Output
6
5
2
1
Example 3:
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream()
8 .sorted(Comparator.reve
9 .forEach(name -> System
10 }
11 }
Expand
Output
charlie
bob
Dave
Alice
Person with a few attributes, instantiate multiple objects of the class, and then
sort these objects in ascending order based on a specific attribute.
Code
JAVA
1 import java.util.*;
2
3 class Person {
4 String name;
5 int age;
6
7 public Person(String name, int ag
8 this.name = name;
9 this.age = age;
10 }
11 }
Expand
Output
Alice
Bob
Charlie
Person class with name and age attributes and a constructor. In the
main method of the Main class, we create an ArrayList of Person objects
and add three Person instances with different names and ages.
4. distinct()
The
Syntax
JAVA
1 stream.distinct()
Example 1:
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream()
8 .distinct()
9 .forEach(name -> System
10 }
11 }
Expand
Output
bob
Alice
distinct() method has removed the duplicate strings from the stream and returned
a new stream. On the new stream, we have performed a terminal operation using the
forEach() method and displayed the unique strings on the console.
Example 2:
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<Integer> numbers = Array
6
7 numbers.stream()
8 .distinct()
9 .forEach(number -> Sy
10 }
11 }
Expand
Output
2
5
4. Terminal Operations
let's learn some of the commonly used methods to perform terminal operations on
streams:
1. forEach()
2. count()
3. collect()
4. anyMatch()
5. allMatch()
6. noneMatch()
1. forEach()
The
forEach() method works similar to the map() . It iterates over the elements in
the stream and performs the specified operation on each element. Unlike map() ,
the forEach() method does not return any stream.
It accepts a
Syntax
JAVA
1 stream.forEach(Consumer);
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 names.stream() // stream so
8 .filter((eachName) -> e
9 .forEach(name -> System
10 }
11 }
Expand
Output
Alice
Charlie
forEach() method to display the elements of the resultant stream on the console.
2. count()
The
count() method returns a long integer that indicates the number of elements
present in the stream.
Syntax
JAVA
1 stream.count();
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 long namesCount = names.stre
8 .filte
9 .count
10
11 System.out.println(namesCount
Expand
Output
In the above code, we have filtered the names that has greater than 4 letters and used
the
3. collect()
The
collect() method accepts a Collector (interface) type and returns the result
after performing the specified operation.
Syntax
JAVA
1 stream.collect(Collector);
There is a
collect() Method
Let's learn how to calculate the sum of double of numbers in a stream using the
collect() method.
The
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Collectors;
3
4 class Main {
5 public static void main(String[]
6 List<Integer> numbers = Array
7
8 int sumOfNums = numbers.stre
9 .colle
10
11 System.out.println(sumOfNums
Expand
Output
28
Hence, we got the result of the sum of all the elements in the list multiplied by 2.
Collection
Example 1: Converting to a
List
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Collectors;
3
4 class Main {
5 public static void main(String[]
6 List<Integer> numbers = Array
7
8 List<Integer> filteredNums =
9 .filter(
10 .collect
11
Expand
Output
[5, 6, 5]
In the above code, we have created a stream, filtered the numbers that are greater
than 2, and converted the stream of the resultant elements to a
List .
Example 2: Converting to a
Set
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Collectors;
3
4 class Main {
5 public static void main(String[]
6 List<Integer> numbers = Array
7
8 Set<Integer> set = numbers.st
9 .filter(num
10 .collect(Col
11
Expand
Output
[5, 6]
In the above code, we have created a stream, filtered the numbers that are greater
than 2, and converted the stream of the resultant elements to a
Set .
As the
Set contains only unique elements it returned only [5, 6] as the unique
elements after filtering.
Example 3: Converting to a
Map
The
Code
JAVA
1 import java.util.*;
2 import java.util.stream.Collectors;
3
4 class Main {
5 public static void main(String[]
6 List<String> words = Arrays.
7
8 Map<String, Integer> wordLeng
9 .collect(Collectors.t
10 word -> word
11 word -> word
Expand
Output
word -> word as the first argument to the toMap() method which maps the
keys. As the second argument, the lambda expression word -> word.length() has
been provided that calculates the word length and maps the value to its
corresponding key.
Method Description
4. anyMatch()
The
anyMatch() method is used to check if any of elements in the stream has matched
a condition. It returns a boolean data type.
It accepts a
Syntax
JAVA
1 stream.anyMatch(Predicate);
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 boolean isNamePresent = name
8 .anyMatch(eachName -
9
10 System.out.println(isNamePre
11 }
Expand
Output
true
In the above code, we have created a stream of strings and checked if any of the
given names is greater than 4 in length. In the names provided, one of the names
Alice is greater than 4 in length. So, the true text is displayed on the console.
5. allMatch()
The
allMatch() method is used to check if all the elements in the stream match a
condition. It returns a boolean data type.
It accepts a
Syntax
JAVA
1 stream.allMatch(Predicate);
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 boolean isNamePresent = name
8 .allMatch(eachName -
9
10 System.out.println(isNamePre
11 }
Expand
Output
false
In the above code, we have created a stream of strings and checked if all the given
names are greater than 4 in length. In the names provided, one of the names Bob is
not greater than 4 in length. So, the false text is displayed on the console.
6. noneMatch()
The
It accepts a
Syntax
JAVA
1 stream.noneMatch(Predicate);
Code
JAVA
1 import java.util.*;
2
3 class Main {
4 public static void main(String[]
5 List<String> names = Arrays.
6
7 boolean isNamePresent = name
8 .noneMatch(eachName
9
10 System.out.println(isNamePre
11 }
Expand
Output
true
In the above code, we have created a stream of strings and checked that none of the
given names is less than 2 in length. The true text is displayed on the console as
none of the given names is less than 2 in length.
Summary
Stream
A stream does not store the elements, it simply provides a way to access
them.
Terminal operations
forEach() : used to iterate and perform the specified operation on each
element of the stream.