Tuesday, September 2, 2014

Explain Stream API introduced in Java 8 ?

What is a Stream ?
A stream is a sequence of data elements supporting sequential and parallel aggregate operations. Computing the sum of all elements in a stream of integers, mapping all names in list to their lengths, etc. are examples of aggregate operations on streams.

How is it different than Collection ?
Collections focus on the storage of data elements for efficient access whereas streams focus on aggregate computations on data elements from a data source that is typically, but not necessarily, collections.

Few other differences are -
• Streams have no storage.
• Streams can represent a sequence of infinite elements.
• The design of streams is based on internal iteration.
• Streams are designed to be processed in parallel with no additional work from the developers.
• Streams are designed to support functional programming.
• Streams support lazy operations.
• Streams can be ordered or unordered.
• Streams cannot be reused.

What is ParallelStream ?

Java provides two main functionalities out of the box -
a) Partitioning of the stream of data into smaller streams to make parallel processing possible.
b) Parallel processing of the data

Creating a Stream

Streams can be created in multiple ways -

• Stream from Values
Stream<String> stream = Stream.of("Ken", "Jeff", "Chris", "Ellen");
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
IntStream oneToFive = IntStream.range(1, 6);

• Stream from Functions
Stream<Long> oddNaturalNumbers = Stream.iterate(1L, n -> n + 2);
Stream.iterate(1L, n -> n + 2)

• Stream from Arrays
IntStream numbers = Arrays.stream(new int[]{1, 2, 3});
• Stream from Collections
// Create and populate a set of strings
Set<String> names = new HashSet<>();
// Create a sequential stream from the set
Stream<String> sequentialStream = names.stream();
// Create a parallel stream from the set
Stream<String> parallelStream = names.parallelStream();

• Stream from Files, etc
Stream<String> lines = Files.lines(path)

Operations on Streams (Bulk Operations, Map and Reduce)

Take Odd numbers from the stream square them and them add them all
int sum = Stream.of(1, 2, 3, 4, 5)
.peek(e -> System.out.println("Taking integer: " + e))
.filter(n -> n % 2 == 1)
.peek(e -> System.out.println("Filtered integer: " + e))
.map(n -> n * n)
.peek(e -> System.out.println("Mapped integer: " + e))
.reduce(0, Integer::sum);
Sum = 35

Increase Income of All Females by 10%
.forEach(p -> p.setIncome(p.getIncome() * 1.10));
• Square all the numbers in the array
IntStream.rangeClosed(1, 5)
.map(n -> n * n)

Get All males having income greater than 5000
.filter(p -> p.isMale() && p.getIncome() > 5000.0)

Get Combined Income of All Employees
double sum = Person.persons()
.reduce(0.0, Double::sum);

Find first line from log file that contains word 'password
Stream<String> lines = Files.lines(path);
Optional<String> passwordEntry = lines.filter(s -> s.contains("password")).findFirst();

Remove All Nulls from a Stream of Objects