java.util.stream – Stream APIs basics | Java8
In this article we will walk through basic overview of java.util.stream package. Package java.util.stream contains classes that support functional type of operations on streams of elements, such as map-reduce transformation, filtering etc. By the end of the article we will be able to answer following questions:
1. What is streams?
2. How it can be created?
3. Stream operations?
4. Difference between stream and collections?
1. What is streams?
Let's start our quest with first question, java helps us to process our data in more declarative way as we can do in SQL queries. Java stream doesn't store data. It operates on the source data structure (ex: collection and array) and produce pipelined data that we can use and perform specific operations. In addition to that java stream APIs also help us to use parallelism as these APIs supports many parallel operations to process the data.
2. How it can be created?
There are many ways to create stream.
- Collection framework have introduced stream instance method using default method in interface. So you can get stream from any collection object via stream() or parallelStream() method.
- From arrays also we can get the stream object using, Arrays.stream(Object[]);
- Stream class also holds static factory methods to create streams, ex. Stream.of(Object[]), IntStream.range(int, int) or Stream.iterate(Object, UnaryOperator);
- Streams of random numbers can be obtained from Random.ints();
- The lines of a file can be obtained from BufferedReader.lines();
Lets see some examples of creating stream objects:
Generating stream using collection:
List<Integer> myList = new ArrayList<>();
for(int i=0; i<100; i++) myList.add(i);
//sequential stream
Stream<Integer> sequentialStream = myList.stream();
Using Stream.of method:
Stream<Integer> stream = Stream.of(1,2,3,4);
Using Arrays.stream:
LongStream is = Arrays.stream(new long[]{1,2,3,4});
3. Stream operations:
Stream operations mainly divided into two section and they are combined to form a pipeline:
a) Intermediate Operations:
Intermediate operations return a new stream. They are always lazy; executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed.
Some of the frequently used intermediate operations are: filter, map, sorted
b) Terminal Operations:
Terminal operations, such as Stream.forEach or IntStream.sum, may traverse the stream to produce a result or a side-effect. After the terminal operation is performed, the stream pipeline is considered consumed, and can no longer be used; if you need to traverse the same data source again, you must return to the data source to get a new stream. In almost all cases, terminal operations are eager, completing their traversal of the data source and processing of the pipeline before returning. Only the terminal operations iterator() and spliterator() are not; these are provided as an "escape hatch" to enable arbitrary client-controlled pipeline traversals in the event that the existing operations are not sufficient to the task.
Some of the frequently used terminal operators are: collect, count, forEach, findFirst
Let's take an example to understand the stream operations:
Stream stream = myList.stream(); List<Integer>results = stream.filter(s -> s%2 == 0) .collect(Collectors.toList());
In above example, we have one list of Integers named myList. We want to filter all the elements whose modulo 2 is zero and store it to new arraylist named result. So first we will open a stream from myList collection using stream method. Now to filer the elements we are using intermediate operator which will return a new stream with filtered elements and the using terminal operator collect we are converting it to type of list and assigning it to results list.
4. Difference between stream and collections?
A collection is an in-memory data structure to hold values and before we start using collection, all the values should have been populated. Whereas a java Stream is a data structure that is computed on-demand.
Java Stream doesn't store data, it operates on the source data structure (collection and array) and produce pipelined data that we can use and perform specific operations. Such as we can create a stream from the list and filter it based on a condition. It uses lambda expressions which makes our code more declarative, short and readable.
For this article, we have covered very basic understanding on stream in our next article we will cover streams in more details.
That's all for this topic. If you guys have any suggestions or queries, feel free to drop a comment. We would be happy to add that in our post. You can also contribute your articles by creating contributor account here.
Happy Learning 🙂
If you like the content on CodePumpkin and if you wish to do something for the community and the planet Earth, you can donate to our campaign for planting more trees at CodePumpkin Cauvery Calling Campaign.
We may not get time to plant a tree, but we can definitely donate ₹42 per Tree.
About the Author
Tags: Core Java, Java8, Java8 Features, Stream API
Comments and Queries
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:<pre><code class="java"> String foo = "bar"; </code></pre>For more information on supported HTML tags in disqus comment, click here.