Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use Stream API for simple iteration?

Are there any benefits in using the new Stream API for simple iterations?

Without Stream API:

 for (Map.Entry<String, String> entry : map.entrySet()) {
        doSomething(entry);
    }

Using Stream API:

map.entrySet().stream().forEach((entry) -> {
        doSomething(entry);
    });

Length and readability of code are about the same. Are there any important differences (e.g. in performance)?

like image 516
Viet Norm Avatar asked Apr 24 '14 10:04

Viet Norm


2 Answers

The Streams API makes parallelism much easier to accomplish (although you'll only see the benefit with a large sized collection). If you had to implement parallelism on your first example then there would be a sizeable difference in the amount of code (as opposed to adding .parallelStream() to the second example)

As per the Java Trail on parallelism:

One difficulty in implementing parallelism in applications that use collections is that collections are not thread-safe, which means that multiple threads cannot manipulate a collection without introducing thread interference or memory consistency errors. The Collections Framework provides synchronization wrappers, which add automatic synchronization to an arbitrary collection, making it thread-safe. However, synchronization introduces thread contention. You want to avoid thread contention because it prevents threads from running in parallel. Aggregate operations and parallel streams enable you to implement parallelism with non-thread-safe collections provided that you do not modify the collection while you are operating on it. Note that parallelism is not automatically faster than performing operations serially, although it can be if you have enough data and processor cores. While aggregate operations enable you to more easily implement parallelism, it is still your responsibility to determine if your application is suitable for parallelism.

like image 184
Shiraaz.M Avatar answered Oct 07 '22 12:10

Shiraaz.M


You had asked about Streams, but as skiwi's comment noted, passing a lambda to the forEach default method on Map possibly fills the bill if the iteration is simple and doesn't require parallelism or any additional logic. Assuming that doSomething can be refactored to take separate key and value args instead of a Map.Entry, this can be reduced to a one-liner:

    map.forEach(MyClass::doSomething);  // if doSomething is a static method

    map.forEach(this::doSomething);     // if doSomething is an instance method
like image 3
Stuart Marks Avatar answered Oct 07 '22 12:10

Stuart Marks