The java.util.stream.Stream class is one of the most useful class of Java 8 API. If I have to say that this is the class you would be using mostly while coding in Java 8 then it won't be an exaggeration. Since Stream class is integrated with Collection framework, you will end up using Streams for most of your day to day programming task in Java 8. It has several useful methods e.g. map() to convert one type of collection to other, flatMap to flatten a collection of collection, forEach to iterate over Collection, filter to selective remove elements from collection.
Similarly, toArray to convert Stream to array, collect to accumulate elements of Stream into any list or collection, peek to debug stream pipeline, reduce to perform reduction on any stream, sort to arrange elements of stream in order, reverse to reverse stream elements, distinct to remove duplicate elements from stream etc.
Since these methods are quite common for day to day programming activity, a good knowledge of Stream API is must for any Java developer.
In order to educate Java programmers with essential methods of Stream class, I am going to share these 10 examples. In this article, you will learn how to use map, flatMap, recdue, forEach, filter, toArray, collect, distinct, sort, reverse, mapToInt, mapToDouble etc.
Once you learn and understand how to use these methods of Stream class, you are quite ready to write code in new Java 8 style, provided you know how to use lambda expression and method reference.
If you don't then first read my post on lambda expression and method reference to get yourself familiar with those concepts.
1. Java 8 Stream map Example
The map method allows you to transform a collection by applying a method on all elements of stream obtained from that collection.
For example, you have a Stream of String object and you want a collection of Integer where each element is the length of corresponding String.
In order to achieve that you can use map() method of java.util.Stream. This method accepts a functional interface required to transform each element. This means you can pass either a lambda expression or method reference to this method.
Another example of Stream.map() function is to convert a list of labels into a list of Buttons i.e. you have a list of Label object and you want to create a List of Buttons having those labels.
You can do so easily by using map() function and constructor reference as shown below:
listOfLabels.stream().map(Button::new).collect(Collectors.toList());
2. Java 8 Stream flatMap Example
The flatMap of Steam class allows you to flatten a Stream and then perform map operation. This is particularly useful when you have a Collection of Collection. For example, you have
List<Integer> listOfEvenNumbers = Arrays.asList(2, 4, 6, 8, 10);
List<Integer> listOfOddNumbers = Arrays.asList(1, 3, 5, 7, 9);
List<List<Integer>> listOfList = new ArrayList<>();
listOfList.add(listOfEvenNumbers);
listOfList.add(listOfOddNumbers);
// not really a list of numbers
System.out.println("list of list: " + listOfList);
// using flatmap to convert a list of list to just a list
List<Integer> listOfNumbers = listOfList.stream()
.flatMap(numbers -> numbers.stream())
.collect(Collectors.toList());
System.out.println("list of numbers: " + listOfNumbers);
Output
list of list: [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
list of numbers: [2, 4, 6, 8, 10, 1, 3, 5, 7, 9]
3. Java 8 Stream reduce Example
This method performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
List<Integer> listOfPrimes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
int total = listOfPrimes.stream().reduce(Integer::sum).orElse(0);
System.out.println("first 10 prime numbers: " + listOfPrimes);
System.out.println("total of first 10 prime numbers: " + total);
Output
first 10 prime numbers: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
total of first 10 prime numbers: 129
4. Java 8 Stream forEach Example
The forEach() method of Stream class allow you to loop through all elements of Stream similar to enhanced for loop of Java 5.
In case of parallel stream the order of processing is not guaranteed by forEach() method, so if you need ordered processing, you can use forEachOrdered() method.
List<Integer> listOfPrimes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
System.out.println("looping over first 10 prime numbers: " + listOfPrimes);
listOfPrimes.stream().forEach(System.out::println);
looping over first 10 prime numbers: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
2
3
5
7
11
13
17
19
23
29
5. Java 8 Stream filter Example
The filter() method is another essential method of java.util.Stream class. It allos you to selectivly choose elements from a stream. For example, suppose you have a stream of numbers and you want to print all even numbers.
In that case, you can use filter() method to filter in all even numbers from stream for printing. The filter() method expect a functional interface called Predicate which has a single abstract method test() which returns boolean.
If the element pass the condition and return true, it is preserved in the stream for further processing, otherwise it is discarded. Since filter accept a functional interface, you can pass a lambda expression or method reference to it.
List<Integer> listOfInts = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println("filtering list of numbers: " + listOfInts);
List<Integer> listOfEven = listOfInts.stream()
.filter(x -> x % 2 == 0)
.collect(Collectors.toList());
System.out.println("list of evens: " + listOfEven);
Output
filtering list of numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list of evens: [2, 4, 6, 8, 10]
6. Java 8 Stream to array Example
The java.util.stream.Stream provides a convenient toArray() method to convert a Java 8 Stream to array. The toArray() method is overloaded, the version which doesn't take any parameter return an Object[] which might not be very useful for callers.
The second one which accept a generator return an array of T i.e. if you have a Stream of String elements then it will return a String array. If you have a Stream of Integer values then it will return an Integer[] and so on.
You can pass a constructor reference to this method for creating a specified type of Array as shown below
stream.toArray(String[]::new)
The toArray() method will use constructor reference to create a right type of array and then fill all elements from Stream into it before returning it to client.
Here is an example of converting Stream of String objects into a String array in Java:
Stream<String> bigEconomies = Stream.of("USA", "China", "Japan", "Germany", "France", "India");
String[] largestEconomies = bigEconomies.toArray(String[]::new);
The String[]::new is a constructor reference which is similar to a method which accept an integer e.g. length of array and return a String array. It is also equivalent to lambda expression int length -> new String[length];
7. Java 8 Stream to list Example
You can use Collectors to convert a Java 8 Stream to List. The Collector class is responsible for accumulating elements of Stream into any Collection object.
It provides convenient methods like toList() and toCollection() to gather all elements of Stream into a list or a collection.
Suppose, you have a Stream of Integer objects and you want a List of Integer then you can write following code to convert Java 8 Stream to List:
Stream<Integer> streamOfPrimes = Stream.of(2, 3, 5, 7, 11);
List<Integer> listOfPrimes = streamOfPrimes.collect(Collectors.toList());
The Collectors.toList() method will return you a List containing all elements of Stream.
8. Java 8 Stream peek Example
The peek() method of java.util.Stream class is a debug utility
This is an intermediate operation.
List<String> result = Stream.of("Java", "Android", "JavaScript", "iOS")
.filter(e -> e.length() > 4)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toLowerCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
Output
Filtered value: Android
Mapped value: android
Filtered value: JavaScript
Mapped value: javascript
9. Java 8 Stream collect Example
The collect() method of Stream class allows you to collect elements of a Stream into a Collection object e.g. a List, Map or Set using Collectors.
The Collector interface provide several methods for collecting stream elemetns e.g. toList() to accumulate elements into a List, toMap() to get a Map from Stream, and toCollection() to copy elements into any kind of Collection.
For example, suppose you have a Stream of Book and you want a Set of unique books then you can use collect() method with Collectors.toSet() to achieve that.
You can also get the list of Books by using Collectors.toList() but you must remember that toList() method doesn't provide any guarantee about type, thread-safety and mutability of the List returned. It could be ArrayList, LinkedList or any custom implementation of List interface.
If you want a specific Collection class e.g. ArrayList, you must use the overloaded version of Collectors.toList(ArrayList::new) which allow you to pass constructor reference of specified collection class.
10. Java 8 Stream mapToInt Example
The mapToInt() function of Stream class allow you to convert an Stream into an IntStream, a specialized stream for primitive int value.
This IntStream then provides many useful recude option e.g. sum, average, count, min, max etc to calculate sum, average, count, min or max of all numbers in the stream.
This is an intermediate operation, hence you can use those reduce function on stream after getting an IntStream.
10. Java 8 Stream mapToLong Example
Similar to mapToInt() function, the mapToLong() function converts a Stream into a stream of primitive long values.
It also has similar function to perform aggregation and sorting e.g. sum, average, count, min, max, or sort. Similar to mapToInt() function, mapToLong is also an intermediate operation.
11. Java 8 Stream mapToDouble Example
The mapToDouble() function allows you to create a specialized version of Stream class for primitive double values.
Similar to other primitive streams e.g. IntStream and LongStream, DoubleSream also supports various parallel and aggregate operations e.g. count, max, min, sum or average.
It also has a method called summaryStatistics(), which returns a DoubleSummaryStatistics describing various summary data about the elements of this stream.
More examples
If you want to contribute, write text and code examples for following scenarios and post in comments:
Java 8 Stream sort Example
Java 8 Stream reverse Example
Java 8 Stream distinct Example
Java 8 Stream count Example
Java 8 Stream contains Example
Java 8 Stream HashMap Example
Java 8 Stream findFirst Example
That's all about 10 most useful Java 8 Stream examples. Once you done all these examples by yourself, you would have good command of basic functionalities of Stream class in Java 8. In these examples, you have learned how to use map, flatMap, reduce, forEach, filter, toArray, collect, sort, reverse, distinct, count, contains, mapToInt, mapToLong and mapToDouble methods of java.util.Stream class.
good examples thank you
ReplyDelete