➤ How to Code a Game
➤ Array Programs in Java
➤ Java Inline Thread Creation
➤ Java Custom Exception
➤ Hibernate vs JDBC
➤ Object Relational Mapping
➤ Check Oracle DB Size
➤ Check Oracle DB Version
➤ Generation of Computers
➤ XML Pros & Cons
➤ Git Analytics & Its Uses
➤ Top Skills for Cloud Professional
➤ How to Hire Best Candidates
➤ Scrum Master Roles & Work
➤ CyberSecurity in Python
➤ Protect from Cyber-Attack
➤ Solve App Development Challenges
➤ Top Chrome Extensions for Twitch Users
➤ Mistakes That Can Ruin Your Test Metric Program
Java 8 Stream Operations with Examples | We will see the different methods of Java 8 Stream which are very commonly used in the code. Also see:- Java 8 Interview Questions
filter
Fetch all numbers from a list that are greater than 5.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = numbers.stream()
.filter(n -> n > 5)
.collect(Collectors.toList());
System.out.println(result); // [6, 7, 8, 9, 10]
map
Transform a list of strings into a list of their uppercase versions.
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> result = words.stream()
.map(str -> str.toUpperCase())
.collect(Collectors.toList());
System.out.println(result); // [APPLE, BANANA, CHERRY]
flatMap
Given a list of lists of subjects, flatten them into a single list of subjects.
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("English", "Science"),
Arrays.asList("Math", "Computer Science")
);
List<String> subjects = listOfLists.stream()
.flatMap(subject -> subject.stream())
.collect(Collectors.toList());
System.out.println(subjects); // [English, Science, Math, Computer Science]
distinct
Remove duplicates from a list of integers.
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4);
List<Integer> results = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(results); // [1, 2, 3, 4]
sorted
Sort a list of names in reverse alphabetical order.
List<String> names = Arrays.asList("John", "Jane", "Alice", "Bob");
List<String> results = names.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(results); // [John, Jane, Bob, Alice]
Instead of
we can also use sorted(
Comparator.reverseOrder())
or sorted(
Collections.reverseOrder())sorted((a, b) -> b.compareTo(a))
.
peek
Print each element in a list while converting them to uppercase.
List<String> names = Arrays.asList("John", "Jane", "Alice", "Bob");
List<String> results = names.stream()
.map(name -> name.toUpperCase())
.peek(System.out::println)
.collect(Collectors.toList());
System.out.println(results);
Output:-
JOHN
JANE
ALICE
BOB
[JOHN, JANE, ALICE, BOB]
The peek
method in Java Streams is primarily used for debugging purposes. It allows to perform an intermediate operation on each element of the stream without modifying the stream itself.
limit
Find the first 3 smallest numbers in a given list of integers.
List<Integer> numbers = Arrays.asList(10, 2, 13, 40, 5, 26, 77, 58, 91, 11);
List<Integer> results = numbers.stream()
.sorted()
**.limit(3)**
.collect(Collectors.toList());
System.out.println(results); // [2, 5, 10]
skip
Fetch all the elements except the first 3 smallest numbers from a list of integers.
List<Integer> numbers = Arrays.asList(10, 2, 13, 40, 5, 26, 77, 58, 91, 11);
List<Integer> results = numbers.stream()
.sorted()
.skip(3)
.collect(Collectors.toList());
System.out.println(results); // [11, 13, 26, 40, 58, 77, 91]
forEach
Print each element of a list of strings with the prefix “Item: “.
List<String> words = Arrays.asList("apple", "banana", "cherry");
words.stream()
.forEach(word -> System.out.println("Item: " + word));
// Item: apple, Item: banana, Item: cherry
collect
Collect a list of integers into a Set
.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 4, 5);
Set<Integer> result = numbers.stream()
.collect(Collectors.toSet());
// result: [1, 2, 3, 4, 5]
reduce
The reduce
method in Java Streams is used to perform a reduction on the elements of a stream, combining them into a single result. It applies a binary operation (a function that takes two arguments and returns a single result) to the elements of the stream, repeatedly, until all elements have been processed and a single value remains.
Compute the product of all numbers in a list.
List<Integer> numbers = Arrays.asList(10, 2, 13, 40);
Integer results = numbers.stream()
.reduce((a,b) -> a*b)
.get();
System.out.println(results); // 10400
Compute the sum of all numbers in a list.
List<Integer> numbers = Arrays.asList(10, 2, 13, 40);
Integer results = numbers.stream()
.reduce((a,b) -> a+b)
.get();
System.out.println(results); // 65
allMatch
The allMatch
method in Java Streams is used to check if all elements in the stream satisfy a given predicate. It returns true
if every element in the stream matches the predicate, and false
otherwise.
Check if all numbers in the list are positive.
List<Integer> numbers = Arrays.asList(10, 2, 13, 40);
Boolean results = numbers.stream().allMatch(a -> a > 0);
System.out.println(results); // true
anyMatch
The anyMatch
method checks whether at least one element in the stream matches a given predicate. It returns true
as soon as it finds an element that satisfies the predicate and stops further processing. If no elements match, it returns false
.
Check if any number in the list is greater than 10.
List<Integer> numbers = Arrays.asList(5, 8, 12, 3);
boolean result = numbers.stream()
.anyMatch(n -> n > 10);
System.out.println(result); // true
noneMatch
The noneMatch
method in Java Streams is used to check if no elements in the stream match a given predicate. It returns true
if none of the elements satisfy the predicate and false
if at least one element does.
Check if no elements in the list are negative.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean result = numbers.stream()
.noneMatch(n -> n < 0);
System.out.println(result); // true
findFirst
The findFirst
is used to retrieve the first element in a stream that matches a given condition or simply the first element in the stream if no filtering is applied. It returns the first element wrapped in an Optional
, which is a container object that may or may not contain a non-null value.
Find the first element in a list that starts with the letter ‘b’.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
String result = words.stream()
.filter(s -> s.startsWith("b"))
.findFirst().get();
System.out.println(result); // banana
findAny
It retrieves any element from the stream that matches a given condition, or simply any element from the stream if no filtering is applied. It returns the element wrapped in an Optional
, which may or may not contain a value.
Find any element in a list that starts with the letter ‘b’.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
String result = words.stream().filter(s -> s.startsWith("b")).findAny().get();
System.out.println(result);
max
andmin
They are used to find the maximum and minimum elements in a stream, respectively, based on a given comparator or natural ordering. These methods return an Optional
because the stream might be empty. Both methods return an Optional<T>
to handle the case where the stream might be empty.
Find the maximum and minimum values from a list of integers.
List<Integer> numbers = Arrays.asList(5, 1, 8, 3, 9);
Integer max = numbers.stream().max(Integer::compareTo).get();
Integer min = numbers.stream().min(Integer::compareTo).get();
System.out.println(max + " " + min); // 9 1
Or, the same can be done as:-
Integer max = numbers1.stream().max((a, b) -> a.compareTo(b)).get();
Integer min = numbers1.stream().min((a, b) -> a.compareTo(b)).get();
toArray
Convert a list of Strings into an array.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
// String[] result = words.toArray(new String[0]);
String[] result = words.toArray(String[]::new);
System.out.println(Arrays.toString(result));
// [apple, banana, cherry, blackberry]
joining
It is used to concatenate the elements of a stream into a single String
. It’s part of the Collectors
utility class and provides a convenient way to aggregate elements into a string format with optional delimiters, prefixes, and suffixes. Method:- joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
Concatenate all strings in a list into a single string separated by commas.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
String result = words.stream().collect(Collectors.joining(", "));
System.out.println(result);
// apple, banana, cherry, blackberry
String concatedString1 = words.stream().collect(Collectors.joining(", ", "[", "]"));
System.out.println(concatedString1); // [apple, banana, cherry, blackberry]
count
Count the number of strings in a list.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
long count = words.stream().count();
System.out.println(count); // 4
Count the number of strings starting with “b” in a given list.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
long count = words.stream().filter(s -> s.startsWith("b")).count();
System.out.println(count); // 2
counting
The counting
method in Java Streams is a collector that counts the number of elements in the stream. It’s often used in conjunction with other collectors for aggregation. It is very similar to the previous count() method.
Return Type: A Collector<T, ?, Long>
that counts the elements in the stream.
Count the number of strings in a list.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blackberry");
long count = words.stream()
.filter(s -> s.startsWith("b")).collect(Collectors.counting());
System.out.println(count); // 2
Complex Java 8 Stream Operations
groupingBy
It groups elements of the stream by a specified classifier function. It is a powerful feature provided by the Collectors
utility class and is commonly used for aggregating and categorizing data into a Map
where the keys are the result of applying the classifier function and the values are lists of items corresponding to each key.
Group a list of employee by their city.
public class Employee {
private String name;
private String city;
// setter, getter, constructor, toString
}
List<Employee> employees = Arrays.asList(
new Employee("John", "New York"),
new Employee("Jane", "London"),
new Employee("Jack", "New York")
);
Map<String, List<Employee>> employeeByCity = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity));
System.out.println(employeeByCity);
// or
employees.stream().collect(Collectors.groupingBy(e -> e.getCity()));
Output:-
{
NewYork=[
Employee(name=John, city=NewYork),
Employee(name=Jack, city=NewYork)
],
London=[
Employee(name=Jane, city=London)
]
}
partitioningBy
The partitioningBy
method in Java Streams is used to partition the elements of a stream into two groups based on a specified predicate. It returns Map
where the keys are Boolean
, and the values are lists of elements that satisfy (or do not satisfy) the predicate.
Return Type: A Map<Boolean, List<T>>
where:
- Key
true
contains elements that satisfy the predicate. - Key
false
contains elements that do not satisfy the predicate.
Partition a list of integers into even and odd numbers.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Map<Boolean, List<Integer>> result = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
System.out.println(result);
// {false=[1, 3, 5], true=[2, 4, 6]}
- Use Case: Categorizing employees based on their performance ratings.
- Predicate: Employees with performance ratings above a certain threshold (e.g., 4.0).
- True group: High-performing employees.
- False group: Regular-performing employees.
Map<Boolean, List<Employee>> employeePartition = employeeList.stream()
.collect(Collectors.partitioningBy(employee -> employee.getPerformanceRating() > 4.0));
This can be useful for HR departments to identify high-performing employees for rewards, promotions, or additional training programs.
summarizingInt
The summarizingInt
method in Java Streams is a collector that generates summary statistics for the elements of a stream, including count, sum, minimum, average, and maximum.
Return Type: An IntSummaryStatistics
object containing the summary statistics.
Generate summary statistics (count, sum, min, average, max) for a list of integers.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// IntSummaryStatistics stats = numbers.stream()
// .mapToInt(x -> x).summaryStatistics();
IntSummaryStatistics stats = numbers.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
System.out.println(stats);
// IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}
System.out.println(stats.getAverage() + " " + stats.getSum()); // 3.0 15
mapping
The mapping
method in Java Streams is used to apply a mapping function to the elements of a stream and then collect the results using another collector.
Return Type: A Collector
that applies a mapping function and collects the results.
Extract and collect the lengths of all strings in a list.
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<Integer> lengths = words.stream()
.collect(Collectors.mapping(String::length, Collectors.toList()));
System.out.println(lengths); // [5, 6, 6]
Use case:- Extract customer email addresses from a list of orders for sending marketing or order status updates.
List customerEmails = orderList.stream()
.collect(Collectors.mapping(order -> order.getCustomer().getEmail(), Collectors.toList()));
joining with delimiter, prefix, and suffix
The joining
method in Java Streams concatenates the elements of a stream into a single String, with optional delimiters, prefixes, and suffixes.
Return Type: A Collector
that concatenates the elements of a stream into a single String
.
Concatenate all strings in a list into a single string with commas, a prefix, and a suffix.
List<String> words = Arrays.asList("apple", "banana", "cherry");
String result = words.stream()
.collect(Collectors.joining(", ", "[", "]"));
System.out.println(result); // [apple, banana, cherry]
groupingBy with downstream collector
The groupingBy
method in Java Streams groups the elements of the stream by a classifier function and can also apply a downstream collector to the results.
Return Type: A Map<K, D>
where K
is the type of the classifier, and D
is the result of the downstream collector.
Group a list of strings by their length and count the number of strings in each group.
List<String> words = Arrays.asList("apple", "banana", "cherry", "blueberry");
Map<Integer, Long> groupedByLength = words.stream()
.collect(Collectors.groupingBy(String::length, Collectors.counting()));
System.out.println(groupedByLength); // {5=1, 6=2, 9=1}
Use case: We can use groupingBy
to group orders by customer and then count how many orders each customer has placed using counting
as a downstream collector.
Map<Customer, Long> ordersByCustomer = orderList.stream()
.collect(Collectors.groupingBy(Order::getCustomer, Collectors.counting()));
filtering
The filtering
method is used to filter elements of a stream and then collect the results using another collector.
Return Type: A Collector
that filters elements and collects the results.
Filter and collect only the even numbers from a list of integers.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evens = numbers.stream()
.collect(Collectors.filtering(n -> n % 2 == 0, Collectors.toList()));
System.out.println(evens); // [2, 4, 6, 8, 10]
collectingAndThen
The collectingAndThen
method in Java Streams is a collector that first applies a collection operation and then applies another function to the result.
Return Type: A Collector<T, A, R>
that first collects elements and then transforms the result.
Convert a stream of strings into a set and then get its size.
List<String> words = Arrays.asList("apple", "banana", "cherry", "banana");
int count = words.stream()
.collect(Collectors.collectingAndThen(Collectors.toSet(), Set::size));
System.out.println(count); // 3
mapping with downstream collector
The mapping
method is used to apply a mapping function to elements in a stream and then collect the results using another collector.
Return Type: A Collector<T, A, R>
that applies a mapping function and collects the results.
Collect the lengths of all strings in a list and sum them.
List<String> words = Arrays.asList("apple", "banana", "cherry");
int totalLength = words.stream()
.collect(Collectors.mapping(String::length,
Collectors.summingInt(Integer::intValue)));
System.out.println(totalLength); // 17
toMap
The toMap
method in Java Streams converts the elements of a stream into a Map
using a key and a value mapping function.
Return Type: A Map<K, V>
where K
is the key type and V
is the value type.
Convert a list of strings into a map where the key is the string and the value is its length.
List<String> words = Arrays.asList("apple", "banana", "cherry");
Map<String, Integer> map = words.stream()
.collect(Collectors.toMap(Function.identity(), String::length));
System.out.println(map); // {banana=6, apple=5, cherry=6}
Use case:- create a map where each order ID is associated with its total amount.
Map<Long, Integer> orderAmountMap = orderList.stream()
.collect(Collectors.toMap(Order::getId, Order::getTotalAmount));
toConcurrentMap
The toConcurrentMap
method in Java Streams is similar to toMap
, but it produces a ConcurrentMap
for thread-safe operations. When multiple threads might access or modify the map simultaneously, This collector ensures that the resulting map is thread-safe and can be safely used in concurrent environments.
Return Type: A ConcurrentMap<K, V>
where K
is the key type and V
is the value type.
Convert a list of strings into a concurrent map where the key is the string and the value is its length.
List<String> words = Arrays.asList("apple", "banana", "cherry");
ConcurrentMap<String, Integer> map = words.stream()
.collect(Collectors.toConcurrentMap(Function.identity(), String::length));
System.out.println(map); // {banana=6, apple=5, cherry=6}
reducing
The reducing
method in Java Streams is used to perform a reduction on the elements of the stream using an associative accumulation function.
It takes 2 arguments-
- Identity Value (optional): A starting value that serves as the initial result and is used as the default when the stream is empty.
- Binary Operator: A function that takes two arguments and returns a combined result.
Return Type: AnOptional<T>
if no identity is provided orT
if an identity is provided.
Find the sum of a list of integers.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.collect(Collectors.reducing(0, Integer::sum));
System.out.println(sum); // 15
collect(Collectors.reducing(0, (a, b) -> a + b));
flatMapping
The flatMapping
method is used to flatten a stream of collections and then apply a collector to the flattened elements.
Return Type: A Collector
that applies a flat-mapping function and collects the results.
Flatten a list of lists of integers and collect the result as a single list.
List<List<Integer>> listOfLists = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9)
);
List<Integer> flattenedList = listOfLists.stream()
.collect(Collectors.flatMapping(Collection::stream, Collectors.toList()));
System.out.println(flattenedList); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
groupingByConcurrent
The groupingByConcurrent
method in Java Streams is similar to groupingBy
, but it returns a ConcurrentMap
for thread-safe operations.
Return Type: A ConcurrentMap<K, List<T>>
where K
is the type of the classifier.
Group a list of strings by their length in a thread-safe manner.
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
ConcurrentMap<Integer, List<String>> groupedByLength = words.stream()
.collect(Collectors.groupingByConcurrent(String::length));
System.out.println(groupedByLength);
// {4=[date], 5=[apple], 6=[banana, cherry]}
teeing
The teeing
method in Java Streams allows combining two collectors into one, where the results of the two collectors are then combined into a final result.
Return Type: A Collector<T, ?, R>
that combines the results of two collectors.
Compute both the sum and the count of a list of integers and return the result as a pair.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Map<String, Integer> result = numbers.stream()
.collect(
Collectors.teeing(
Collectors.summingInt(Integer::intValue),
Collectors.counting(),
(sum, count) -> Map.of("sum", sum, "count", count.intValue())
)
);
System.out.println(result); // {sum=15, count=5}
If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!