Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Count frequency(Specialized) in Java 8 using Lambdas

I have a list of strings like this: "na","na","na","uk","uk". I want to count the frequency of each element in such a way that if the existing map’s value is even, then I will add 1; otherwise 2.

 List<String> streamer=Arrays.asList("na","na","na","uk","uk");
        Map<String,Integer> m=new HashMap<>();
        for(String s:streamer)
        {
            if(m.containsKey(s))
            {
                if(m.get(s)%2==0)
                    m.put(s,m.get(s)+1);
                else
                    m.put(s,m.get(s)+2);
            }
            else
                m.put(s,1);
        }
        System.out.println("CUSTOM Frequency::::"+m); 

Now, I want to achieve the exact same thing using streams and lambdas. All I could do is this:

Map<String, Long>map4 = streamer.stream()
                .collect(Collectors.groupingBy(Function.identity(),
                        Collectors.counting())); //How can I get custom counting instead of Collectors.counting()?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Besides @Sweeper’s answer to get the expected counting result, if your question also implied how to customize a collect operation, you could use the method of() of the Collector class.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/Collector.html#of(java.util.function.Supplier,java.util.function.BiConsumer,java.util.function.BinaryOperator,java.util.stream.Collector.Characteristics…)

The method accepts a supplier, an accumulator as a BiConsumer and a combiner as a BinaryOperator. The supplier simply provides the container where to store the result, in your case a Map<String, Long>. The accumulator populates the container by putting or updating an entry with the custom frequency logic. Lastly, The combiner simply merges the sub-results of parallel executions in case the stream is executed as a parallel stream.

List<String> streamer = Arrays.asList("na", "na", "na", "uk", "uk");
Map<String, Long> map4 = streamer.stream()
        .collect(Collector.of(
                HashMap::new,
                (Map<String, Long> map, String s) -> {
                    if (!map.containsKey(s)) {
                        map.put(s, 1L);
                    } else {
                        map.computeIfPresent(s, (String key, Long val) -> val % 2 != 0 ? val + 2 : val + 1);
                    }
                },
                (Map<String, Long> map1, Map<String, Long> map2) -> {
                    map1.putAll(map2);
                    return map1;
                }
        ));

Output

{na=5, uk=3}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading