使用 java 8 对列表中对象的属性进行计数

2022-09-03 05:28:49

因此,让我们假设我有一个对象。该类的对象如下所示:ArraylistAnimal

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

我想做的是,计算一下每个动物存在多少种不同的颜色,并把它们放在一个地方是名字,是不同颜色的数量。ArrayListMap<String,Integer>StringInteger

例如,如果有4只黑狗和1只白狗,则与地图相当的值为

map.put("Dog",2);

我知道可以使用它来完成,但我不知道如何。Stream


答案 1

您要执行的操作是使用 name 属性作为键的分组操作。这是最容易的部分。更棘手的是将“不同颜色的计数”表示为下游收集器。由于JRE中没有这样的收集器,因此我们必须利用存储来构建一个收集器。请注意,即使有内置的,它也必须在引擎盖下使用类似的存储。因此,我们将元素映射到颜色,将它们收集到 Sets 中(这意味着仅保留不同的值),并通过查询大小来完成Set

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帖子:https://stackoverflow.com/a/30282943/1138523


推荐