Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find counts of distinct objects using Java streams [duplicate]

I have a list of Thing objects:

class Thing {
    public String id;
    public String name;
}

List<Thing> lst contains following;

[{'1', 'AB'},{'2', 'CD'},{'1', 'AB'},{'1','AB'},{'2','CD'},{'3','EF'}]

Now I want to use Java streams or any util functions to get a distinct count on id: I want the output to be,

id   count
1    3
2    2 
3    1

How can I achieve this?

like image 391
user1015388 Avatar asked Dec 09 '18 02:12

user1015388


2 Answers

You can get it using Collectors.groupingBy the id attribute and then counting its occurrences as:

List<Thing> objects = new ArrayList<>(); // initalise as in the question 
Map<String, Long> countForId = objects.stream()
        .collect(Collectors.groupingBy(Thing::getId, Collectors.counting()));
like image 89
Naman Avatar answered Sep 28 '22 23:09

Naman


one could also use the toMap collector:

lst.stream().collect(toMap(Thing::getId, v -> 1, Math::addExact));

creates a Map<String, Integer> where the Thing::getId is the key mapper used to select the map keys and v -> 1 is the value mapper used to select the map values and in the case of a key collision we add the corresponding values with the merge function Math::addExact.

or Map::merge:

Map<String, Integer> accumulator = new HashMap<>();
lst.forEach(t -> accumulator.merge(t.getId(), 1, Math::addExact));

Same idea as above, if the Thing::getId is already present in the accumulator map, we merge them with Math::addExact otherwise we accumulate the provided key and value into the map.

if the order matters as shown in your post, then instead of HashMap above, you can use a LinkedHashMap.

You could also provide a map into which the elements are to be accumulated into to preserve order in the toMap collector with:

lst.stream().collect(toMap(Thing::getId, v -> 1, Math::addExact, LinkedHashMap::new));

or using the groupingBy collector:

lst.stream()
   .collect(Collectors.groupingBy(Thing::getId, 
                LinkedHashMap::new,
                Collectors.counting()));
like image 45
Ousmane D. Avatar answered Sep 28 '22 22:09

Ousmane D.