Java 8 stream have always been the most exciting concept to understand and apply. I have got a chance to apply streams api's in my project and thoroughly enjoyed it.
This post is about, covering basic streams concepts to the best of my experience. I will try to keep it as simple as possible for easy understanding.
Before we begin on streams, it would be good if we take a look at concept of
Map , Filter & Reduce algorithm.
This concept is a generic and not related to java but will help us to understand stream in a much better and quicker way.
Let's understand this algorithm with an example. Again, I always prefer example with my passion being Running! :-)
So, let's say, we need to find out Average age of Runners older than 40.
If we solve this scenario with Map, Filter and Reduce algorithm, it will comprises below steps,
Step 1 -> Mapping
Creates a List of Runner and Returns a List of Integer. Here, size of the returned list will be same but it will have integer holding Runners Age.
Takes List<Runner> and returns List<Integer> =
Resulting List type differs but Size is same.
Step 2 -> Filtering
Now, you are telling that, filter out List<Integer> which returns only Runner with age greater than 40.
Takes List<Integer> and returns List<Integer> =
Resulting List type same, but size differs after filter is applied.
Step 3 -> Reduce
At this step, you will just apply aggregation function ( here Avg ) on the filtered list from step 2.
Takes List<Integer> and returns Average Age of Runner older than 40.
This is how Streams works internally!
Let's understand some basics of Streams
What is Stream all about
# An Object on which we define operations, like Map, Filter and Reduce are operations.
# An Object which does NOT hold any data and that's the biggest difference between Collection and Stream.
# An Object that should not change data that it processes.
when I say, should not, meaning it a rule, one should follow while working with streams. Compiler will never report anything here!
# An object which is capable of processing data in one pass.
Suppose you have stream of Account collection, now while processing this stream, there should not be any intermediary collection created as part of this processing.
# Is a typed Interface
public interface Stream<T> extends BaseStream<T, Stream<T>>
Stream interface can take any of type of data for streaming, it could be stream of String, Integer, Customer etc etc.
You would have noticed that there is only one stream can operate at a time, so if you have two streams in operation ( say, two streams.filter statement ) then you will get a runtime error as below
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
This post is about, covering basic streams concepts to the best of my experience. I will try to keep it as simple as possible for easy understanding.
Before we begin on streams, it would be good if we take a look at concept of
Map , Filter & Reduce algorithm.
This concept is a generic and not related to java but will help us to understand stream in a much better and quicker way.
Let's understand this algorithm with an example. Again, I always prefer example with my passion being Running! :-)
So, let's say, we need to find out Average age of Runners older than 40.
If we solve this scenario with Map, Filter and Reduce algorithm, it will comprises below steps,
Step 1 -> Mapping
Creates a List of Runner and Returns a List of Integer. Here, size of the returned list will be same but it will have integer holding Runners Age.
Takes List<Runner> and returns List<Integer> =
Resulting List type differs but Size is same.
Step 2 -> Filtering
Now, you are telling that, filter out List<Integer> which returns only Runner with age greater than 40.
Takes List<Integer> and returns List<Integer> =
Resulting List type same, but size differs after filter is applied.
Step 3 -> Reduce
At this step, you will just apply aggregation function ( here Avg ) on the filtered list from step 2.
Takes List<Integer> and returns Average Age of Runner older than 40.
This is how Streams works internally!
Let's understand some basics of Streams
What is Stream all about
# An Object on which we define operations, like Map, Filter and Reduce are operations.
# An Object which does NOT hold any data and that's the biggest difference between Collection and Stream.
# An Object that should not change data that it processes.
when I say, should not, meaning it a rule, one should follow while working with streams. Compiler will never report anything here!
# An object which is capable of processing data in one pass.
Suppose you have stream of Account collection, now while processing this stream, there should not be any intermediary collection created as part of this processing.
# Is a typed Interface
public interface Stream<T> extends BaseStream<T, Stream<T>>
Stream interface can take any of type of data for streaming, it could be stream of String, Integer, Customer etc etc.
# Efficient data Processing - Large or small amount of data
Efficiently process data - in Parallel and in Pipelined ( avoiding intermediary computations ).
public class StreamBasic {
public static void main(String ... args) {
//Creating Stream of Strings
Stream<String> stream = Stream.of("Sprint", "TempoRun", "NegativeSplit", "LongRun", "Intervals"); // MAP
//Prints all elements of Streams
/*stream.forEach( s -> System.out.println(s));*/
// Applied Predicate with only string lenght > 10
Predicate<String> p = s -> s.length() > 10;
//filter strings greater than of lenght 10*/
/*stream
.filter(p)
.forEach(System.out::println); */
List<String> runTypes = new ArrayList<>();
Predicate<String> p1 = Predicate.isEqual("LongRun");
Predicate<String> p2 = Predicate.isEqual("TempoRun");
//Prints only elements from stream when p1 or p2 is present
/* stream
.filter(p1.or(p2))
.forEach(s -> System.out.println(s)); */
/*prints stream elements using Peek method and then applying filter with only p1 or p2 predicates and finally adding result to the list*/
stream
.peek(System.out::println)
.filter(p1.or(p2))
.forEach(runTypes::add);
System.out.println("List size=>"+runTypes.size());
}
}
Efficiently process data - in Parallel and in Pipelined ( avoiding intermediary computations ).
public static void main(String ... args) {
//Creating Stream of Strings
Stream<String> stream = Stream.of("Sprint", "TempoRun", "NegativeSplit", "LongRun", "Intervals"); // MAP
//Prints all elements of Streams
/*stream.forEach( s -> System.out.println(s));*/
// Applied Predicate with only string lenght > 10
Predicate<String> p = s -> s.length() > 10;
//filter strings greater than of lenght 10*/
/*stream
.filter(p)
.forEach(System.out::println); */
List<String> runTypes = new ArrayList<>();
Predicate<String> p1 = Predicate.isEqual("LongRun");
Predicate<String> p2 = Predicate.isEqual("TempoRun");
//Prints only elements from stream when p1 or p2 is present
/* stream
.filter(p1.or(p2))
.forEach(s -> System.out.println(s)); */
/*prints stream elements using Peek method and then applying filter with only p1 or p2 predicates and finally adding result to the list*/
stream
.peek(System.out::println)
.filter(p1.or(p2))
.forEach(runTypes::add);
System.out.println("List size=>"+runTypes.size());
}
}
You would have noticed that there is only one stream can operate at a time, so if you have two streams in operation ( say, two streams.filter statement ) then you will get a runtime error as below
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
No comments:
Post a Comment