Java 8 Streams

1) What Are Streams?
Streams can be defined as a sequences of elements from a source which support data processing operations. You can treat streams as operations on data.

2) Why Streams?
Almost every Java application use Collections API to store and process the data. Despite being the most used Java API, it is not easy to write the code for even some common data processing operations like filtering, finding, matching, sorting, mapping etc using Collections API . So, there needed Next-Gen API to process the data. So Java API designers have come with Java 8 Streams API to write more complex data processing operations with much of ease.

3) Characteristics Of Java 8 Streams:
3.1) Streams are not the data structures
Streams doesn’t store the data. You can’t add or remove elements from streams. Hence, they are not the data structures. They are the just operations on data.
3.2) Stream Consumes a data source
Stream consumes a source, performs operations on it and produces the result. Source may be a collection or an array or an I/O resource. Remember, stream doesn’t modify the source.
3.3) Intermediate And Terminal Operations
Most of the stream operations return another new stream and they can be chained together to form a pipeline of operations.
The operations which return stream themselves are called intermediate operations. For example – filter(), distinct(), sorted() etc
The operations which return other than stream are called terminal operations. count(). min(), max() are some terminal operations.
3.4) Pipeline Of Operations
A pipeline of operations consists of three things – a source, one or more intermediate operations and a terminal operation. Pipe-lining of operations let you to write database-like queries on a data source. In the below example, int array is the source, filter() and distinct() are intermediate operations and forEach() is a terminal operation.

IntStream.of(new int[] {4, 7, 1, 8, 3, 9, 7}).filter(i -> i > 5).distinct().forEach(System.out::println);

3.5) Internal Iteration
Collections need to be iterated explicitly. i.e you have to write the code to iterate over collections. But, all stream operations do the iteration internally behind the scene for you. You need not to worry about iteration at all while writing the code using Java 8 Streams API.
3.6) Parallel Execution
To gain the performance while processing the large amount of data, you have to process it in parallel and use multi core architectures. Java 8 Streams can be processed in parallel without writing any multi threaded code. For example, to process the collections in parallel, you just use parallelStream() method instead of stream() method.

List names = new ArrayList<>();
 names.add("ABC");
 names.add("XYZ");
 names.add("PQR"); 
 //Normal Execution
 names.stream().filter(name -> name.length() > 5).skip(2).forEach(System.out::println);
 //Parallel Execution
 names.parallelStream().filter(name -> name.length() > 5).skip(2).forEach(System.out::println);

3.7) Streams are lazily populated
All elements of a stream are not populated at a time. They are lazily populated as per demand because intermediate operations are not evaluated until terminal operation is invoked.
3.8) Short Circuiting Operations
Short circuiting operations are the operations which don’t need the whole stream to be processed to produce a result. For example – findFirst(), findAny(), limit() etc.
3.9) Streams are traversable only once
You can’t traverse the streams more than once just like iterators. If you traverse the stream first time, it is said to be consumed.

List nameList = Arrays.asList("ABC", "LMN", "PQR", "XYZ");
 Stream stream = nameList.stream();
 stream.forEach(System.out::println);
 stream.forEach(System.out::println);    //Error : stream has already been operated upon or closed

4. Java Stream API:

5. Reducing Operations
Reducing operations are the operations which combine all the elements of a stream repeatedly to produce a single value. For example, counting number of elements, calculating average of elements, finding maximum or minimum of elements etc.

int sum = Arrays.stream(new int[] {7, 5, 9, 2, 8, 1}).reduce(0, (a, b) -> a+b);    // 32

There is another form of reduce() method which takes no initial value. But returns an Optional object.

OptionalInt sum = Arrays.stream(new int[] {7, 5, 9, 2, 8, 1}).reduce((a, b) -> a+b);     //Output : OptionalInt[32]
 OptionalInt min = Arrays.stream(new int[] {7, 5, 9, 2, 8, 1}).min();     //Output : OptionalInt[1] 
//Here, min() of IntStream will be used as we are passing an array of ints

6. Use of Peek() Method:

  • Type Of Operation : Intermediate Operation
  • What It Does? : Performs an additional action on each element of a stream. This method is only to support debugging where you want to see the elements as you pass in a pipeline.
List names = new ArrayList<>();
 names.add("David");
 names.add("Johnson");
 names.add("Samontika");
 names.add("Brijesh");
 names.add("John"); 
 names.add("David");
 names.stream()
         .filter(name -> name.length() > 5)
         .peek(e -> System.out.println("Filtered Name :"+e))
         .map(String::toUpperCase)
         .peek(e -> System.out.println("Mapped Name :"+e))
         .toArray();
 //Output :
 //Filtered Name :Johnson
 //Mapped Name :JOHNSON
 //Filtered Name :Samontika
 //Mapped Name :SAMONTIKA
 //Filtered Name :Brijesh
 //Mapped Name :BRIJESH

7. Finding And Matching Operations

  • 1. anyMatch() : Any one element matches
  • Type Of Operation : Short-circuiting Terminal Operation
  • What It Does? : Returns true if any one element of a stream matches with given predicate. This method may not evaluate all the elements of a stream. Even if the first element matches with given predicate, it ends the operation.
List names = new ArrayList<>();         
 names.add("David");         
 names.add("Johnson");         
 names.add("Samontika");         
 names.add("Brijesh");
 names.add("John");         
 if(names.stream().anyMatch((String name) -> name.length() == 5)) {
     System.out.println("Yes… There is a name exist with 5 letters");
 }
  • 2. allMatch() : All elements matches
  • Type Of Operation : Terminal Operation
  • What It Does? : This method returns true if all the elements of a stream matches with given predicate. Otherwise returns false.
List names = new ArrayList<>();
 names.add("Sampada");
 names.add("Johnson");
 names.add("Samontika");
 names.add("Brijesh"); 
 if(names.stream().allMatch((String name) -> name.length() > 5))
 {
     System.out.println("All are big names");
 }
  • 3. noneMatch() : No element matches
  • Type Of Operation : Terminal Operation
  • What It Does? : Returns true only if all the elements of a stream doesn’t match with given predicate.
List names = new ArrayList<>();
 names.add("David");         
 names.add("Johnson");
 names.add("Samontika");
 names.add("Brijesh");
 names.add("John");          
 if(names.stream().noneMatch((String name) -> name.length() == 2))
 {
     System.out.println("There is no two letter name");
 }
  • 4. findFirst() : Finding first element.
  • Type Of Operation : Short-circuiting Terminal Operation
  • What It Does? : Returns first element of a stream wrapped in an Optional object.
Optional firstElement = Stream.of("First", "Second", "Third", "Fourth").findFirst();    //Output : Optional[First]
  • 5. findAny() : Finding any element.
  • Type Of Operation : Short-circuiting Terminal operation
  • What It Does? : Randomly returns any one element in a stream. The result of this operation is unpredictable. It may select any element in a stream. Multiple invocations on the same source may not return same result.
Optional anyElement = Stream.of("First", "Second", "Third", "Four").findAny();
  • Convert Stream to Array:
Type Of Operation : Terminal Operation
 What It Does? : Returns an array containing elements of a stream.
 List names = new ArrayList<>();         
 names.add("David");         
 names.add("Johnson");         
 names.add("Samontika");         
 names.add("Brijesh");         
 names.add("John");      
 //Storing first 3 names in an array
 Object[] streamArray = names.stream().limit(3).toArray();         
 System.out.println(Arrays.toString(streamArray));        
 //  Output: [David, Johnson, Samontika]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.