Showing posts with label Stream API. Show all posts
Showing posts with label Stream API. Show all posts

Thursday, August 20, 2015

Loop iteration redefined with java 8 Stream


for loop is there in many programming languages like C, C++ java C# etc and it is used mainly iterating contents of same type.

for loop has come a long way in Java 8 with new forEach() method in java.util.stream.Stream class.

We will check in the following post how every release of java has given us more and more compact and enhanced looping experience by time.

Pre JDK 1.5, this was the way of iterating over an Collection let’s say ArrayList:
// Before JDK 1.5, printing each element of List using for
List  countries = Arrays.asList("India", "Australia", "England", "South Africa");

for(int i=0; i < countries.size(); i++)
{
  System.out.println(countries.get(i));
}
So when foreach loop or advanced for loop was added on Java 5, we started to following style of looping over Collection or List :
for(String country : countries){
      System.out.println(country);
}
This was much shorter, cleaner and less error prone than previous one and everybody loved it. You don't need to keep track of index, you don't need to call size() method in every step and it was less error prone than previous one, but it was still imperative. You are telling compiler what to do and how to do like traditional for loop.

Now comes the era of Lambda Expressions where things changes drastically when functional style of programming was introduced in Java 8 via lambda expression and new Stream API. Now you can loop over your collection without any loop in Java, you just need to use forEach() method of java.util.Stream class, as shown below :

countries.stream().forEach(str -> System.out.println(str));


This code has reduced looping over collection or list into just one line.
To add into, If you want to perform some pre processing task e.g. filtering, conversion or mapping, you can also do this in same line, as shown below:

countries.stream().filter(country ->
country.contains("n")).forEach(str -> System.out.println(str));


📥 Get Your Free Java Interview Question Guide

Don't just read—learn! Get 10 essential Java interview questions with complete solutions delivered to your inbox. Perfect for interview prep or skill refreshing.

Enter your email below:

We'll send you the PDF plus Java tips. Unsubscribe anytime.

Tuesday, August 18, 2015

Stream Collection types

Java is inheritably sequential and there is no direct mean to introduce parallel processing at library level, Stream API is going to fill that gap. By using this, you can filter elements of collection on given criterion e.g. if you have a List of employees, you can filter all employees based upon their name, department and so on.

Stream API allows you to process Collection both sequentially and parallel. This is also useful for bulk data operation. You can create a sequential and parallel stream as follows :

List employees = getListOfEmployees();
 
// sequential version
Stream  stream = employees.stream();
 
//parallel version
Stream  parallelStream = employees.parallelStream();

Collection and Stream

Collection interface is enhanced to provide stream support. It now has a stream() method which returns a sequential Stream with this collection as its source. Once you get the reference of stream, you can perform bulk data operations with this collection.

One of the important things to note is that Stream do not modify the original source. For every operation, a new Stream is created and original collection remains unmodified. Similarly, you cannot reuse Stream either. Reusing a closed stream will throw IllegalStateException as shown below:

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.(AbstractPipeline.java:203)
    at java.util.stream.ReferencePipeline.(ReferencePipeline.java:94)
    at java.util.stream.ReferencePipeline$StatelessOp.(ReferencePipeline.java:618)
    at java.util.stream.ReferencePipeline$2.(ReferencePipeline.java:163)
    at java.util.stream.ReferencePipeline.filter(ReferencePipeline.java:162)
    at Test.main(Test.java:33)

It supports functional programming idioms such as map and reduce along with parallel processing capability, support for filtering elements from Collection.


Stream operations 

Stream operations are mainly divided into two categories : intermediate and terminal operations. Intermediate operations such as filter() or map() returns a new Stream, while terminal operations such as Stream.forEach() produce a result or side effect. After the terminal operation, the stream pipeline is considered consumed, and can no longer be used.

Intermediate operations are also of two types stateless and stateful. As name suggests, stateless operations doesn't retain any state from previously processed element. For example : filter() and map(). On the other hand distinct() and sorted() are example of stateful operations, which can have state from previously processed elements, while processing new elements.

Important methods in java.util.stream

Return Type
Method Name
Short Description
Long
count()
Returns the count of elements in this stream
Stream
Distinct()
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
static Stream
Empty()
Returns an empty sequential Stream.
Stream
Filter(Predicate predicate)
Returns a stream consisting of the elements of this stream that match the given predicate.
Stream
flatMap(Function> mapper)
Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
void
forEach(Consumer action)
Performs an action for each element of this stream.
static Stream
generate(Supplier s)
Returns an infinite sequential unordered stream where each element is generated by the provided Supplier.
static Stream
iterate(T seed, UnaryOperator f)
Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.
Stream
Limit(long maxSize)
Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
Stream
map(Function mapper)
Returns a stream consisting of the results of applying the given function to the elements of this stream.
Optional  
max(Comparator comparator)
Returns the maximum element of this stream according to the provided Comparator.
Optional  
min(Comparator comparator)
Returns the minimum element of this stream according to the provided Comparator.
Stream
skip(long n)
Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
Stream
sorted()
Returns a stream consisting of the elements of this stream, sorted according to natural order.
Stream
Sorted (Comparator comparator)
Returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.
Object[]
toArray()
Returns an array containing the elements of this stream.

Traditional Threads vs. Virtual Threads: A Performance Benchmark on Spring Boot 4

Traditional Threads vs. Virtual Threads: A Performance Benchmark on Spring Boot 4 Bottom line: For high-concurrency Spring Boot apps on mo...