Java Stream API

Education is not limited to just classrooms. It can be gained anytime, anywhere... - Ravi Ranjan (M.Tech-NIT)

Java 8 Stream

Java provides a new additional package in Java 8 called java.util.stream. This package consists of classes, interfaces and enum to allows functional-style operations on the elements. You can use stream by importing java.util.stream package.


Stream provides following features:

  • Stream does not store elements. It simply conveys elements from a source such as a data structure, an array, or an I/O channel, through a pipeline of computational operations.

  • Stream is functional in nature. Operations performed on a stream does not modify it's source. For example, filtering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing elements from the source collection.

  • Stream is lazy and evaluates code only when required.

  • The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream must be generated to revisit the same elements of the source.

You can use stream to filter, collect, print, and convert from one data structure to other etc. In the following examples, we have apply various operations with the help of stream.

Java Stream Interface Methods

Methods

Description

boolean allMatch(Predicate predicate)

It returns all elements of this stream which match the provided predicate. If the stream is empty then true is returned and the predicate is not evaluated.

boolean anyMatch(Predicate predicate)

It returns any element of this stream that matches the provided predicate. If the stream is empty then false is returned and the predicate is not evaluated.

static Stream.Builder builder()

It returns a builder for a Stream.

R collect(Collector collector)

It performs a mutable reduction operation on the elements of this stream using a Collector. A Collector encapsulates the functions used as arguments to collect(Supplier, BiConsumer, BiConsumer), allowing for reuse of collection strategies and composition of collect operations such as multiple-level grouping or partitioning.

R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)

It performs a mutable reduction operation on the elements of this stream. A mutable reduction is one in which the reduced value is a mutable result container, such as an ArrayList, and elements are incorporated by updating the state of the result rather than by replacing the result.

static Stream concat(Stream a, Stream b)

It creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel. When the resulting stream is closed, the close handlers for both input streams are invoked.

long count()

It returns the count of elements in this stream. This is a special case of a reduction.

Stream distinct()

It returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.

static Stream empty()

It returns an empty sequential Stream.

Stream filter(Predicate predicate)

It returns a stream consisting of the elements of this stream that match the given predicate.

Optional findAny()

It returns an Optional describing some element of the stream, or an empty Optional if the stream is empty.

Optional findFirst()

It returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.

Stream flatMap(Function> mapper)

It returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)

DoubleStream flatMapToDouble(Function mapper)

It returns a DoubleStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have placed been into this stream. (If a mapped stream is null an empty stream is used, instead.)

IntStream flatMapToInt(Function mapper)

It returns an IntStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)

LongStream flatMapToLong(Function mapper)

It returns a LongStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)

void forEach(Consumer action)

It performs an action for each element of this stream.

void forEachOrdered(Consumer action)

It performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.

static Stream generate(Supplier s)

It returns an infinite sequential unordered stream where each element is generated by the provided Supplier. This is suitable for generating constant streams, streams of random elements, etc.

static Stream iterate(T seed,UnaryOperator f)

It returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.

Stream limit(long maxSize)

It returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.

Stream map(Function mapper)

It returns a stream consisting of the results of applying the given function to the elements of this stream.

DoubleStream mapToDouble(ToDoubleFunction mapper)

It returns a DoubleStream consisting of the results of applying the given function to the elements of this stream.

IntStream mapToInt(ToIntFunction mapper)

It returns an IntStream consisting of the results of applying the given function to the elements of this stream.

LongStream mapToLong(ToLongFunction mapper)

It returns a LongStream consisting of the results of applying the given function to the elements of this stream.

Optional max(Comparator comparator)

It returns the maximum element of this stream according to the provided Comparator. This is a special case of a reduction.

Optional min(Comparator comparator)

It returns the minimum element of this stream according to the provided Comparator. This is a special case of a reduction.

boolean noneMatch(Predicate predicate)

It returns elements of this stream match the provided predicate. If the stream is empty then true is returned and the predicate is not evaluated.

@SafeVarargs static Stream of(T... values)

It returns a sequential ordered stream whose elements are the specified values.

static Stream of(T t)

It returns a sequential Stream containing a single element.

Stream peek(Consumer action)

It returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.

Optional reduce(BinaryOperator accumulator)

It performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.

T reduce(T identity, BinaryOperator accumulator)

It performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value.

U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)

It performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions.

Stream skip(long n)

It returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned.

Stream sorted()

It returns a stream consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed.

Stream sorted(Comparator comparator)

It returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.

Object[] toArray()

It returns an array containing the elements of this stream.

A[] toArray(IntFunction generator)

It returns an array containing the elements of this stream, using the provided generator function to allocate the returned array, as well as any additional arrays that might be required for a partitioned execution or for resizing.

Java Example: Filtering Collection without using Stream

In the following example, we are filtering data without using stream. This approach we are used before the stream package was released.

  1. import java.util.*;  
  2. class Product{  
  3.     int id;  
  4.     String name;  
  5.     float price;  
  6.     public Product(int id, String name, float price) {  
  7.         this.id = id;  
  8.         this.name = name;  
  9.         this.price = price;  
  10.     }  
  11. }  
  12. public class JavaStreamExample {  
  13.     public static void main(String[] args) {  
  14.         List<Product> productsList = new ArrayList<Product>();  
  15.         //Adding Products  
  16.         productsList.add(new Product(1,"HP Laptop",25000f));  
  17.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  18.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  19.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  20.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  21.         List<Float> productPriceList = new ArrayList<Float>();  
  22.         for(Product product: productsList){  
  23.               
  24.             // filtering data of list  
  25.             if(product.price<30000){  
  26.                 productPriceList.add(product.price);    // adding price to a productPriceList  
  27.             }  
  28.         }  
  29.         System.out.println(productPriceList);   // displaying data  
  30.     }  
  31. }  

Output:

[25000.0, 28000.0, 28000.0]

Java Stream Example: Filtering Collection by using Stream

Here, we are filtering data by using stream. You can see that code is optimized and maintained. Stream provides fast execution.

  1. import java.util.*;  
  2. import java.util.stream.Collectors;  
  3. class Product{  
  4.     int id;  
  5.     String name;  
  6.     float price;  
  7.     public Product(int id, String name, float price) {  
  8.         this.id = id;  
  9.         this.name = name;  
  10.         this.price = price;  
  11.     }  
  12. }  
  13. public class JavaStreamExample {  
  14.     public static void main(String[] args) {  
  15.         List<Product> productsList = new ArrayList<Product>();  
  16.         //Adding Products  
  17.         productsList.add(new Product(1,"HP Laptop",25000f));  
  18.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  19.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  20.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  21.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  22.         List<Float> productPriceList2 =productsList.stream()  
  23.                                      .filter(p -> p.price > 30000)// filtering data  
  24.                                      .map(p->p.price)        // fetching price  
  25.                                      .collect(Collectors.toList()); // collecting as list  
  26.         System.out.println(productPriceList2);  
  27.     }  
  28. }  

Output:

[90000.0]

Java Stream Iterating Example

You can use stream to iterate any number of times. Stream provides predefined methods to deal with the logic you implement. In the following example, we are iterating, filtering and passed a limit to fix the iteration.

  1. import java.util.stream.*;  
  2. public class JavaStreamExample {  
  3.     public static void main(String[] args){  
  4.         Stream.iterate(1, element->element+1)  
  5.         .filter(element->element%5==0)  
  6.         .limit(5)  
  7.         .forEach(System.out::println);  
  8.     }  
  9. }  

Output:

5
10
15
20
25

Java Stream Example: Filtering and Iterating Collection

In the following example, we are using filter() method. Here, you can see code is optimized and very concise.

  1. import java.util.*;  
  2. class Product{  
  3.     int id;  
  4.     String name;  
  5.     float price;  
  6.     public Product(int id, String name, float price) {  
  7.         this.id = id;  
  8.         this.name = name;  
  9.         this.price = price;  
  10.     }  
  11. }  
  12. public class JavaStreamExample {  
  13.     public static void main(String[] args) {  
  14.         List<Product> productsList = new ArrayList<Product>();  
  15.         //Adding Products  
  16.         productsList.add(new Product(1,"HP Laptop",25000f));  
  17.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  18.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  19.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  20.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  21.         // This is more compact approach for filtering data  
  22.         productsList.stream()  
  23.                              .filter(product -> product.price == 30000)  
  24.                              .forEach(product -> System.out.println(product.name));    
  25.     }  
  26. }  

Output:

Dell Laptop

Java Stream Example : reduce() Method in Collection

This method takes a sequence of input elements and combines them into a single summary result by repeated operation. For example, finding the sum of numbers, or accumulating elements into a list.

In the following example, we are using reduce() method, which is used to sum of all the product prices.

  1. import java.util.*;  
  2. class Product{  
  3.     int id;  
  4.     String name;  
  5.     float price;  
  6.     public Product(int id, String name, float price) {  
  7.         this.id = id;  
  8.         this.name = name;  
  9.         this.price = price;  
  10.     }  
  11. }  
  12. public class JavaStreamExample {  
  13.     public static void main(String[] args) {  
  14.         List<Product> productsList = new ArrayList<Product>();  
  15.         //Adding Products  
  16.         productsList.add(new Product(1,"HP Laptop",25000f));  
  17.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  18.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  19.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  20.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  21.         // This is more compact approach for filtering data  
  22.         Float totalPrice = productsList.stream()  
  23.                     .map(product->product.price)  
  24.                     .reduce(0.0f,(sum, price)->sum+price);   // accumulating price  
  25.         System.out.println(totalPrice);  
  26.         // More precise code   
  27.         float totalPrice2 = productsList.stream()  
  28.                 .map(product->product.price)  
  29.                 .reduce(0.0f,Float::sum);   // accumulating price, by referring method of Float class  
  30.         System.out.println(totalPrice2);  
  31.           
  32.     }  
  33. }  

Output:

201000.0
201000.0

Java Stream Example: Sum by using Collectors Methods

We can also use collectors to compute sum of numeric values. In the following example, we are using Collectors class and it?s specified methods to compute sum of all the product prices.

  1. import java.util.*;  
  2. import java.util.stream.Collectors;  
  3. class Product{  
  4.     int id;  
  5.     String name;  
  6.     float price;  
  7.     public Product(int id, String name, float price) {  
  8.         this.id = id;  
  9.         this.name = name;  
  10.         this.price = price;  
  11.     }  
  12. }  
  13. public class JavaStreamExample {  
  14.     public static void main(String[] args) {  
  15.         List<Product> productsList = new ArrayList<Product>();  
  16.         //Adding Products  
  17.         productsList.add(new Product(1,"HP Laptop",25000f));  
  18.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  19.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  20.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  21.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  22.         // Using Collectors's method to sum the prices.  
  23.         double totalPrice3 = productsList.stream()  
  24.                         .collect(Collectors.summingDouble(product->product.price));  
  25.         System.out.println(totalPrice3);  
  26.           
  27.     }  
  28. }  

Output:

201000.0

Java Stream Example: Find Max and Min Product Price

Following example finds min and max product price by using stream. It provides convenient way to find values without using imperative approach.

  1. import java.util.*;  
  2. class Product{  
  3.     int id;  
  4.     String name;  
  5.     float price;  
  6.     public Product(int id, String name, float price) {  
  7.         this.id = id;  
  8.         this.name = name;  
  9.         this.price = price;  
  10.     }  
  11. }  
  12. public class JavaStreamExample {  
  13.     public static void main(String[] args) {  
  14.         List<Product> productsList = new ArrayList<Product>();  
  15.         //Adding Products  
  16.         productsList.add(new Product(1,"HP Laptop",25000f));  
  17.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  18.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  19.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  20.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  21.         // max() method to get max Product price   
  22.         Product productA = productsList.stream()  
  23.                         .max((product1, product2)->   
  24.                         product1.price > product2.price ? 1: -1).get();  
  25.           
  26.         System.out.println(productA.price);  
  27.         // min() method to get min Product price  
  28.         Product productB = productsList.stream()  
  29.                 .max((product1, product2)->   
  30.                 product1.price < product2.price ? 1: -1).get();  
  31.         System.out.println(productB.price);  
  32.           
  33.     }  
  34. }  

Output:

90000.0
25000.0

Java Stream Example: count() Method in Collection

  1. import java.util.*;  
  2. class Product{  
  3.     int id;  
  4.     String name;  
  5.     float price;  
  6.     public Product(int id, String name, float price) {  
  7.         this.id = id;  
  8.         this.name = name;  
  9.         this.price = price;  
  10.     }  
  11. }  
  12. public class JavaStreamExample {  
  13.     public static void main(String[] args) {  
  14.         List<Product> productsList = new ArrayList<Product>();  
  15.         //Adding Products  
  16.         productsList.add(new Product(1,"HP Laptop",25000f));  
  17.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  18.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  19.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  20.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  21.         // count number of products based on the filter  
  22.         long count = productsList.stream()  
  23.                     .filter(product->product.price<30000)  
  24.                     .count();  
  25.         System.out.println(count);  
  26.     }  
  27. }  

Output:

3

stream allows you to collect your result in any various forms. You can get you result as set, list or map and can perform manipulation on the elements.


Java Stream Example : Convert List into Set

  1. import java.util.*;  
  2. import java.util.stream.Collectors;  
  3. class Product{  
  4.     int id;  
  5.     String name;  
  6.     float price;  
  7.     public Product(int id, String name, float price) {  
  8.         this.id = id;  
  9.         this.name = name;  
  10.         this.price = price;  
  11.     }  
  12. }  
  13.   
  14. public class JavaStreamExample {  
  15.     public static void main(String[] args) {  
  16.         List<Product> productsList = new ArrayList<Product>();  
  17.   
  18.         //Adding Products  
  19.         productsList.add(new Product(1,"HP Laptop",25000f));  
  20.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  21.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  22.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  23.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  24.           
  25.         // Converting product List into Set  
  26.         Set<Float> productPriceList =   
  27.             productsList.stream()  
  28.             .filter(product->product.price < 30000)   // filter product on the base of price  
  29.             .map(product->product.price)  
  30.             .collect(Collectors.toSet());   // collect it as Set(remove duplicate elements)  
  31.         System.out.println(productPriceList);  
  32.     }  
  33. }  

Output:

[25000.0, 28000.0]

Java Stream Example : Convert List into Map

  1. import java.util.*;  
  2. import java.util.stream.Collectors;  
  3. class Product{  
  4.     int id;  
  5.     String name;  
  6.     float price;  
  7.     public Product(int id, String name, float price) {  
  8.         this.id = id;  
  9.         this.name = name;  
  10.         this.price = price;  
  11.     }  
  12. }  
  13.   
  14. public class JavaStreamExample {  
  15.     public static void main(String[] args) {  
  16.         List<Product> productsList = new ArrayList<Product>();  
  17.   
  18.         //Adding Products  
  19.         productsList.add(new Product(1,"HP Laptop",25000f));  
  20.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  21.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  22.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  23.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  24.           
  25.         // Converting Product List into a Map  
  26.         Map<Integer,String> productPriceMap =   
  27.             productsList.stream()  
  28.                         .collect(Collectors.toMap(p->p.id, p->p.name));  
  29.               
  30.         System.out.println(productPriceMap);  
  31.     }  
  32. }  

Output:

{1=HP Laptop, 2=Dell Laptop, 3=Lenevo Laptop, 4=Sony Laptop, 5=Apple Laptop}

Method Reference in stream

  1. import java.util.*;  
  2. import java.util.stream.Collectors;  
  3.   
  4. class Product{  
  5.     int id;  
  6.     String name;  
  7.     float price;  
  8.       
  9.     public Product(int id, String name, float price) {  
  10.         this.id = id;  
  11.         this.name = name;  
  12.         this.price = price;  
  13.     }  
  14.           
  15.     public int getId() {  
  16.         return id;  
  17.     }  
  18.     public String getName() {  
  19.         return name;  
  20.     }  
  21.     public float getPrice() {  
  22.         return price;  
  23.     }  
  24. }  
  25.   
  26. public class JavaStreamExample {  
  27.   
  28.     public static void main(String[] args) {  
  29.           
  30.         List<Product> productsList = new ArrayList<Product>();  
  31.           
  32.         //Adding Products  
  33.         productsList.add(new Product(1,"HP Laptop",25000f));  
  34.         productsList.add(new Product(2,"Dell Laptop",30000f));  
  35.         productsList.add(new Product(3,"Lenevo Laptop",28000f));  
  36.         productsList.add(new Product(4,"Sony Laptop",28000f));  
  37.         productsList.add(new Product(5,"Apple Laptop",90000f));  
  38.           
  39.         List<Float> productPriceList =   
  40.                 productsList.stream()  
  41.                             .filter(p -> p.price > 30000// filtering data  
  42.                             .map(Product::getPrice)         // fetching price by referring getPrice method  
  43.                             .collect(Collectors.toList());  // collecting as list  
  44.         System.out.println(productPriceList);  
  45.     }  
  46. }  

Output:

[90000.0]