JAVA 8 Streams with examples | Stream API JAVA 8 | Tutorials - Scratcharound
First of all make it clear that this api has nothing to do with IO Streams in java just because of the similar names. Java 8 Stream Api is a part of java.util.stream package.
What is JAVA 8 Stream ?
Which means we can get a sequence of Objects from some source like Collection and perform different
sequential operations on each object. Also with the use of streams we can easily perform operations
in a parallel manner for a large Collection of objects which is even more efficient and time saving.
For parallel processing we use parallelStream which is an alternative of stream. We will
discuss parallelStream also later in this tutorial.
Example: Suppose we have a list of Student objects and we want to print the firstName of Student objects for which firstName starts with "J". Now if we use the old approach , we will have to do the iteration twice -
- First to filter the objects with firstName starting with "J".
- Second to Print the filtered content from the newly created list.
The code with the above old approach would look something like this - Code without Stream -
package com.scratcharound.tutorials.java8.streams; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class HelloStream { public static void main(String [] args){ List<Student> students = Arrays.asList( new Student("George","Thomas" ), new Student("Jonney","Stuart" ), new Student("Jackson","Ford" ), new Student("Jack","Pit" ), new Student("Ashley","Benson")); ListWhat if we could do this entire task with just 3 lines of code and without creating a new ArrayList object. Yes we can do this with the help of java 8 stream, see the code below -jStudents = new ArrayList<>(); // first iteration for filtering the list and creating a new list for(Student s : students){ if(s.firstName.startsWith("J")){ jStudents.add(s); } } // Second iteration for printing the newly created list for(Student s : jStudents){ System.out.println(s.firstName); } } }
Code example with Stream
package com.ashu.java8.streams; import java.util.Arrays; import java.util.List; public class HelloStream { public static void main(String [] args){ ListOutput :students = Arrays.asList( new Student("George","Thomas" ), new Student("Jonney","Stuart" ), new Student("Jackson","Ford" ), new Student("Jack","Pit" ), new Student("Ashley","Benson")); students.stream() .filter(i-> i.firstName.startsWith("J")) .forEach(i-> System.out.println(i.firstName)); } }
Jonney
Jackson
Jack
Note : For Using java 8 Streams, you must be familier with java 8
Lambda Expressions.In above example we have done the filtering and printing operations in only one iteration and that too without
creating a new ArrayList.
Code Explaination: In above code stream() is used for getting the stream (a sequential stream) from the
collection, like we obtain Iterator using .iterator() method. This has been provided for all the Collections in java 8.
filter(i-> i.firstName.startsWith("J")) , filters the stream and remove the elements for which the
condition defined in the filter is false. This method takes a
functional interface
Predicate as parameter
which has a abstract method test(T t) that return a boolean value. We have used lambda for this Predicate and
implemented the test(T t) method to return the true or false based on the condition provided.
Finally we have forEach(i-> System.out.println(i.firstName)) method which prints the firstName of the
remaining filtered objects from the stream.
- Java 8 Stream is not a in-memory data structure like collections, but data is computed on demand in Streams.
- Java Stream does not store data, but it performs the operations on data provided by some data source like collection in our case.
- As we have seen in our above example Stream uses functional interface and Lambda interface which makes it suitable for functional programming and writing sort lines of code.
- Java 8 Stream provides internal iterattion for Collections.
- We can also use parallel processiong for larger set of data, with the help of parallel stream.
Stream operations types -
Basically streams has two types of operations -1. Intermediate Operations
2. Terminal Operations
Intermediate Operations are operations which returns a stream after operation so that we can chain multiple intermediate operations without the termination.
As we can see in the example above filter() is an intermediate operation because it returns a filtered stream which we can use to perform further operations.
Terminal Operations are non-stream results, ie either they return a void or some other results which is not a stream. In our example above forEach() is a termination operation which returns void. We can use another termination operation count() on the intermediate stream which returns a long value, the count of stream after filter().
Long size = students.stream() .filter(i-> i.getfName().startsWith("J")) .count(); System.out.println(size);As we have seen above, streams can be created using stream() and parallelStream() method, specially for collections. But we can create strema without using .stream() method by just using of() method by providing a bunch of object references as argument.
See the code given below -
Stream.of(new Student("George","Thomas" ), new Student("Jonney","Stuart" ), new Student("Jackson","Ford" ), new Student("Jack","Pit" ), new Student("Ashley","Benson")).filter(i-> i.firstName.startsWith("J")) .forEach(i-> System.out.println(i.firstName));
Reusing a stream ?
We cannot reuse a stream after calling a termination operation. See code below for example -Streamstream = Stream.of(new Student("George","Thomas" ), new Student("Jonney","Stuart" ), new Student("Jackson","Ford" ), new Student("Jack","Pit" ), new Student("Ashley","Benson")).filter(i-> { System.out.println("Filter "+i.getfName()); return i.firstName.startsWith("J");}); stream.forEach(i-> System.out.println("for each "+i.firstName)); streamSupplier.count(); exception - Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed at java.util.stream.AbstractPipeline.evaluate(Unknown Source) at java.util.stream.ReferencePipeline.anyMatch(Unknown Source) at com.ashu.java8.streams.HelloStream.main(HelloStream.java:33)
above code will throw exception after executing count() termination operation.
To overcome this limitation we will have to create a new stream every time we want to call a termination operation.
This task can be done with the help of java.util.function.Supplier interface of java 8.
Supplier<Stream<Student>> streamSupplier = ()-> Stream.of(new Student("George","Thomas" ), new Student("Jonney","Stuart" ), new Student("Jackson","Ford" ), new Student("Jack","Pit" ), new Student("Ashley","Benson")).filter(i-> { System.out.println("Filter "+i.getfName()); return i.firstName.startsWith("J");}); streamSupplier.get().forEach(i-> System.out.println("for each "+i.firstName)); System.out.println(streamSupplier.get().count());In above example each time we call get() , it will create a new Stream on which we can call a termination operation.
No comments :
Post a Comment