Count elements by type

Viewed 108

How can I map the elements in a list to be counted by their type using the Java Stream API?

Without stream the example looks something like this:

    List<Object> list = new ArrayList<>();
    list.add("Hello");
    list.add(Integer.valueOf(1));
    list.add("World");
    list.add(Double.valueOf(4.6));
    list.add(Integer.valueOf(42));
    list.add(new Object());
    list.add(Integer.valueOf(4711));
    Map<Class<? extends Object>, Integer> map = new HashMap<>();
    for (Object item : list) {
        if (map.containsKey(item.getClass())) {
            int count = map.get(item.getClass());
            map.put(item.getClass(), count + 1);
        } else {
            map.put(item.getClass(), 1);
        }
    }

However in my production code it is not a list of Object, but of an interface with different implementation.

My guess so far is something like this:

workshops.stream().collect(Collectors.groupingBy(Object::getClass))

But how can I map this to Map<Object, Integer> that will also work when Object is replaced by an interface (e.g. List)?

2 Answers

You have the right idea, you're just missing applying a collector (counting, in this case) to each group:

Map<Class<?>, Long> counts =
        workshops.stream()
                .collect(Collectors.groupingBy(Object::getClass,
                         Collectors.counting()));

Use this as your collector:

Collectors.groupingBy(Object::getClass, Collectors.counting())

(Although the value type of the resulting map is Long, notInteger)

Related