Learn in Java
 


   

Java 8 - Stream

 
Java 8 has introduced a new concept called Stream. These are a group of computations specified as a sequence of steps(also called monads). Although, the name sounds similar to Java IO API classes like InputStream/OutputStream, this has nothing to do with them. This is a famous feature in functional programming. Java 8 has adopted this feature of functional programming and named it as Stream.

Streams can work on various input sources like Arrays, Collections etc. A Stream can also be created using a list of objects using Stream interface. This supports various data types. We can also create primitive data type streams using interfaces IntStream, LongStream and DoubleStream.

The below example illustrates some of the possible ways a Stream can be created and manipulated:

package com.learninjava;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * @author learninjava.com
 * @see www.learninjava.com
 */
public class StreamExample1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		List<String> list = new ArrayList<String>();
		
		list.add("Red Bird");
		list.add("Yellow Bird");
		list.add("Blue Bird");
		
		list.stream()
			.map(String::toUpperCase)
			.sorted()
			.forEach(System.out::println);
		
		System.out.println("\n");
		
		Arrays.asList("Red Bird", "Yellow Bird", "Blue Bird")
			  .stream()
			  .forEach(System.out::println);
		
		System.out.println("\n");

		Arrays.stream(new String[]{"Red Bird", "Yellow Bird", "Blue Bird"})
			  .sorted()
			  .forEach(System.out::println);
		
		System.out.println("\n");

		Stream.of("Red Bird", "Yellow Bird", "Blue Bird")
			  .filter(s -> s.contains("l"))
			  .forEach(System.out::println);
			  
		System.out.println("\n");
		
		System.out.println( IntStream.of(3, 2, 1).sum() );		
		
		System.out.println( LongStream.of(3000000, 2000000, 1000000).sum() );

		System.out.println( DoubleStream.of(3.2, 2.9, 1.7).sum() );
		
	}
}

Output:
BLUE BIRD
RED BIRD
YELLOW BIRD


Red Bird
Yellow Bird
Blue Bird


Blue Bird
Red Bird
Yellow Bird


Yellow Bird
Blue Bird


6
6000000
7.8

 

In the example above, Observe how we can apply all functions on the streams using simple commands.

Remember:
One important thing to note in the example is the usage of forEach. forEach is not a method of List but still we can 
use if as if its a part of the List interface. How is this possible ? This is possible because forEach is a default method
in List. This is the realtime usage of a default method in Collections API.

If you open up the source file of Iterable interface you will see forEach method declared as default.

public interface Iterable<T> {

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
...
}
Note that List interface extends Collection interface and Collection interface extends Iterable. This is how forEach works in List.


Stream - Collect, FlatMap, Reduce and ParallelStream



Let us see some advanced stream functions. Most important of them all are below :

Collect - This is used to collect the results into a collection i.e, List, Set or a Map.

FlatMap - A map() function is used to apply a function say toUpperCase and transform the existing stream however, 
it does not return the output as multiple streams. The flatMap() is used to do exactly this, i.e, it returns 
multiple streams from a single stream.

Reduce - Reduce as the name suggests combines multiple elements and reduces it to a single 
result.

ParallelStream - The parallelStream() method is used to run the steps/streams in parallel. Imagine this as if you are 
running the methods in multithreaded environment with a pool of threads. 
Remember:

By default the number of threads in this pool is system dependent. To use a custom pool size, use the below JVM argument when running the below example,

-Djava.util.concurrent.ForkJoinPool.common.parallelism=5

The below example illustrates all of the above functions with examples for each scenario:

package com.learninjava;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author learninjava.com
 * @see www.learninjava.com
 */
public class StreamExample2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		List<String> list = new ArrayList<String>();
		
		list.add("Red Bird");
		list.add("Yellow Bird");
		list.add("Blue Bird");
		list.add("Yellow Bird");
		
		System.out.println("Actual List : " + list);
		
		// Collect example using toSet
		Set<String> set = (Set<String>) list.stream()
											.map(String::toUpperCase)
											.collect(Collectors.toSet());		

		System.out.println("Collect example using toSet : " + set);
		
		// Collect example using toList
		List<String> birdsList = Stream.of("Blue Bird", "White Bird", "Black Bird")
									   .filter(b -> b.contains("l"))
									   .collect(Collectors.toList());
		
		System.out.println("Collect example using toList : " + birdsList);

		// Collect example using toMap
		AngryBird bird1 = new AngryBird(1, "BLUE");
		AngryBird bird2 = new AngryBird(2, "RED");
		AngryBird bird3 = new AngryBird(3, "BLACK");

		List<AngryBird> angryBirdsList = Arrays.asList(bird1, bird2, bird3);

		Map<Integer, String> angryBirdsMap = 
				angryBirdsList.stream()
					     	  .collect(Collectors.toMap(b -> b.size, b -> b.color));
		
		System.out.println("Collect example using toMap : " + angryBirdsMap);
		
		// Using flatMap()
		Egg egg1 = new Egg();
		egg1.size = 1;
		Egg egg2 = new Egg();
		egg2.size = 2;
		
		ArrayList<Egg> eggsList = new ArrayList<Egg>();
		eggsList.add(egg1);
		eggsList.add(egg2);
		
		bird1.eggs = eggsList;
		bird2.eggs = eggsList;
		bird3.eggs = eggsList;

		angryBirdsList.stream()
					  .flatMap(b -> b.eggs.stream())
					  .forEach(e -> System.out.println("Using flatMap() : " + e.size));
		
		// reduce() using Objects
		String biggestSizeBirdColor = angryBirdsList.stream()
				  									.reduce((b1, b2) -> b1.size > b2.size ? b1 : b2)
				  									.get().color;
		System.out.println("reduce() using Objects : " + biggestSizeBirdColor);

		// reduce() using primitives
		List<Integer> birdSizes = Arrays.asList(1, 3, 2, 5, 6);
		int birdSizesTotal = birdSizes.stream()
				 					  .reduce((b1, b2) -> b1 + b2)
				 					  .get();
		System.out.println("reduce() using primitivies : " + birdSizesTotal);
		
		
		// Parallel Streams
		ForkJoinPool commonPool = ForkJoinPool.commonPool();
		System.out.println("Parallel Streams default pool size : " + commonPool.getParallelism());
		
		list = new ArrayList<String>();
		list.add("Red Bird1");
		list.add("Red Bird2");
		list.add("Red Bird3");
		list.add("Red Bird4");
		list.add("Red Bird5");
		list.add("Red Bird6");
		list.add("Red Bird7");
		list.add("Red Bird8");
		list.add("Red Bird9");
		list.add("Red Bird10");

		list.parallelStream()
		    .filter(b -> {
			    System.out.println("Thread Name in filter : " + Thread.currentThread().getName());
			    return true;
		    })
		    .map(b -> {
			    System.out.println("Thread Name in map : " + Thread.currentThread().getName());
			    return b.toUpperCase();
		    })
		    .forEach(System.out::println);
		 
	}
	
}

class AngryBird {
	
	public int size;
	
	public String color;
	
	public List<Egg> eggs = new ArrayList<Egg>();
	
	AngryBird(int size, String color) {
		this.size = size;
		this.color = color;
	}
	
}

class Egg {
	
	public int size;
}

Output:
Actual List : [Red Bird, Yellow Bird, Blue Bird, Yellow Bird]
Collect example using toSet : [RED BIRD, YELLOW BIRD, BLUE BIRD]
Collect example using toList : [Blue Bird, Black Bird]
Collect example using toMap : {1=BLUE, 2=RED, 3=BLACK}
Using flatMap() : 1
Using flatMap() : 2
Using flatMap() : 1
Using flatMap() : 2
Using flatMap() : 1
Using flatMap() : 2
reduce() using Objects : BLACK
reduce() using primitivies : 17
Parallel Streams default pool size : 3
Thread Name in filter : main
Thread Name in map : main
RED BIRD7
Thread Name in filter : main
Thread Name in map : main
RED BIRD6
Thread Name in filter : main
Thread Name in map : main
RED BIRD9
Thread Name in filter : main
Thread Name in map : main
RED BIRD10
Thread Name in filter : main
Thread Name in map : main
RED BIRD8
Thread Name in filter : ForkJoinPool.commonPool-worker-1
Thread Name in filter : ForkJoinPool.commonPool-worker-2
Thread Name in map : ForkJoinPool.commonPool-worker-2
RED BIRD2
Thread Name in filter : ForkJoinPool.commonPool-worker-2
Thread Name in map : ForkJoinPool.commonPool-worker-2
RED BIRD1
Thread Name in filter : ForkJoinPool.commonPool-worker-2
Thread Name in map : ForkJoinPool.commonPool-worker-2
RED BIRD5
Thread Name in filter : ForkJoinPool.commonPool-worker-2
Thread Name in map : ForkJoinPool.commonPool-worker-2
RED BIRD4
Thread Name in map : ForkJoinPool.commonPool-worker-1
RED BIRD3

As you can see from the output that in case of parallel streams, each of the steps are executed by either of the three threads namely ForkJoinPool.commonPool-worker-1, ForkJoinPool.commonPool-worker-2 and main thread. Yes, even the main thread is used as a thread inside the pool. All the other examples are self-explanatory from their output.

Stream in Java 8 is a vast topic and the above quick examples should make give you a quick overview of the new functionality.

 
   

Related Articles

Java 8 Functional Interfaces
Java 8 Lambda Expressions
Equals and HashCode
 
   

Recommended Articles

User and Daemon Threads
Thread States
Restful WebService using CXF
Restful Client using CXF
SOAP WebService using CXF
SOAP Client using CXF




LIKE/SHARE
 
 
 
Download Source:

Comments:


 

Top Picks

1. Top 5 websites offering free e-books

2. Top 10 websites for free Java Articles and Tutorials

3. Top 5 websites for Java Certifications

4. Top 5 Softwares for Java developers




   
   
   
 
 
© Copyright 2017. All rights reserved. All trademarks and logos belongs to their owners.         Website Counter