Считать свойства объектов в списке с помощью java 8

Итак, пусть у меня есть Arraylist объекта Animal. Этот класс объекта выглядит следующим образом:

class Animal{
    String Name;//for example "Dog"
    String Color
}

Что я хочу сделать, подсчитывает, сколько разных цветов существует для каждого животного в Arraylist и помещает их в Map<String,Integer>, где String - это имя и Integer - для количества разных цветов,

Например, если есть 4 черные собаки и 1 белый, эквивалент, помещенный на карту, будет

map.put("Dog",2);

Я знаю, что это можно сделать с помощью Stream, но я не могу узнать, как это сделать.

Ответы

Ответ 1

Что вы хотите сделать, это операция группировки , используя свойство name в качестве ключа. Это легкая часть. Trickier должен выражать "подсчет различных цветов" как нисходящий коллекционер. Поскольку в JRE нет такого сборщика, мы должны построить его, используя хранилище Set. Обратите внимание, что даже если он был встроенным, он должен был использовать аналогичное хранилище под капотом. Поэтому сопоставить элементы с цветами, собрать их в Set s (что подразумевает сохранение только отдельных значений ) и закончить, запросив размер:

Map<String, Integer> map = animalStream.collect(
    Collectors.groupingBy(Animal::getName,
        Collectors.collectingAndThen(
            Collectors.mapping(Animal::getColor, Collectors.toSet()),
            Set::size)));

Ответ 2

Это должно работать:

    Map<String, Integer> map = animal.stream().collect(
            Collectors.groupingBy(
                    Animal::getName,
                    Collectors.collectingAndThen(
                            Collectors.mapping(Animal::getColor, Collectors.toSet()),
                            Set::size)
                    )
            );

Вот некоторый тестовый код:

public static void main(String[] args) {
    List<Animal> animal = new ArrayList<>();
    animal.add(new Animal("Dog","black"));
    animal.add(new Animal("Dog","black"));
    animal.add(new Animal("Dog","blue"));
    animal.add(new Animal("Cat","blue"));
    animal.add(new Animal("Cat","white"));

    Map<String, Integer> map = animal.stream().collect(
            Collectors.groupingBy(
                    Animal::getName,
                    Collectors.collectingAndThen(
                            Collectors.mapping(Animal::getColor, Collectors.toSet()),
                            Set::size)
                    )
            );

    for(Entry<String, Integer> entry:map.entrySet()) {
        System.out.println(entry.getKey()+ " : "+entry.getValue());
    }

}

дает

Cat : 2
Dog : 2

Примечание: этот ответ был вдохновлен этим сообщением SO: fooobar.com/info/385802/...