Lambdas and Streams

Rule 4:Prefer side-effect-free function in streams

Streams Background:
Collector has a method greoupingBy which works similar to group by in SQL . it take two arguments-
Function- It is the property which is to be applied to the input elements.(e.g Function.identity()–returns as it is)
Classifier- It is used to map input elements into the destination map.(Collectors.counting()) Note the key of mapwill be list being grouped because that is the unique thing
and retrns the list
e.g.
List g
= Arrays.asList(“geeks”, “for”, “geeks”);

    // Collect the list as map 
    // by groupingBy() method 
    Map<String, Long> result 
        = g.stream().collect( 
            Collectors.groupingBy( 
                Function.identity(), 
                Collectors.counting())); 

    // Print the result 
    System.out.println(result); 

Note:Issue /discrepency discoeverd – list.stream(0) vsStream.of(list)
list.stream() print exatct result i.e cout of each elemet
where stream.of Just print count of whole lsit as a object and its count as 1
i.e [“geeks”, “for”, “geeks” ]=1

Comparision of stream use cases better vs bad:
Snippet1:
// Uses the streams API but not the paradigm–Don’t do this!
Map freq = new HashMap<>();
try (Stream words = new Scanner(file).tokens()) {
words.forEach(word -> {
freq.merge(word.toLowerCase(), 1L, Long::sum);
});
}
Snippet2:
Map freq;
try (Stream words = new Scanner(file).tokens()) {
freq = words
.collect(groupingBy(String::toLowerCase, counting()));
}

Stream programming is not all about Stream API,It is to be used as part of FUNTIONAL PROGRAMMING PARADIGM to reap maximum benifits.
Use of ForEach for computaion in stream is BAD SMELL CODE.
..
The forEach operation should be used only to report the result of a stream computation, not to perform the computation. Occasionally, it makes sense to use forEach for some other purpose, such as adding the results of a stream computation to a preexisting collection.
General Point: Collectors classs static method can be used by statically importing instead of writing in form Collectors.methodName(),this will add to readability.
Collectors Interface is intimadating as compared to forEach as it has 39 methods.
some inportant method of Collector:
a.comparing(elemntsToBeComparedOn) used for sorting element it’s implementation of Comparator
b.lots of method to convert stream to map
simplest one is: toMap(keyMapper,valueMapper) -Works fine when there unique stream element map to key but when multiple stream elemtns map to same key it throws IllegalStateException,more compilcated form of toMap() provides a way to handle this collision.
One of them is last-write win policy varient of toMap(keyMapper,valueMapper,(v1,v2)->v2) with 3 argumetns

c.groupingBy()-It groups the elements based on CLASSIFIER FUNCTION. the classifier function takes an streams element and return the group to which the elemnt belongs and this group is used as key to Map.
the simplest from is one that takes only one argument- the classifier Function.it return a map whose values are LIST OF ALL ELEMTS IN EACH GROUP.
example:
words.collect(groupingBy(word -> alphabetize(word)))
Two Argument Varient-
if You want the greoupingBy to return elements other than list you can use DOWNSTREAM COLLECTOR. it returns the values of map in eacch category
One of the downstream collector is counting() which return elemtns in each group.DONOT use counting() to get count of elements in stream for that we have Stream method count.
counting is meant to be used as DOWNSTREAM COLLECTOR.
there is no reason to use collect(counting())
d.The final Collectors method is joining, which operates only on streams of CharSequence instances such as STRINGS. In its parameterless form, it returns a collector that simply CONCATENATES the elements.
Its one argument form takes a single CharSequence parameter named delimiter and returns a collector that joins the stream elements, inserting the delimiter between adjacent elements.
In summary, the essence of programming stream pipelines is side-effect-free function objects. This applies to all of the many function objects passed to streams and related objects. The terminal operation forEach should only be used to report the result of a computation performed by a stream, not to perform the computation. In order to use streams properly, you have to know about collectors. The most important collector factories are toList, toSet, toMap, groupingBy, and joining.

Published by

Unknown's avatar

sevanand yadav

software engineer working as web developer having specialization in spring MVC with mysql,hibernate

Leave a comment