Java 8 - Stream API - 分组不起作用

问题描述 投票:0回答:1

我想使用 Stream API 按姓名和城市对人员列表进行分组。 我有以下代码(在 Java 8 中):

class Person {
    private String name;
    private String gender;
    private String city;
    
    Person(String name, String gender, String city) {
        this.name   = name;
        this.gender = gender;
        this.city   = city;
    }
}

class PGroup {
    final String name;
    final String city;
    
    public PGroup(String name, String city) {
        this.name = name;
        this.city = city;
    }       
}

List<Person> people = new ArrayList<>();
people.add(new Person("Thomas", "M", "Cologne"));
people.add(new Person("Wilma",  "F", "Cologne"));
people.add(new Person("Lydia",  "F", "Munich"));
people.add(new Person("Thomas", "M", "Cologne"));

Map<PGroup, List<Person>> map = people.stream()
        .collect(Collectors.groupingBy(t -> new PGroup(t.name, t.city)));

for (PGroup p : map.keySet()) {
    System.out.println("name: " + p.name + ", city: " + p.city);
}

如果我运行这段代码,我会得到:

姓名:威尔玛,城市:科隆
姓名:托马斯,城市:科隆
姓名:Lydia,城市:慕尼黑
姓名:托马斯,城市:科隆

我们可以看到列表根本没有分组。 我预计只有 3 个条目,因为 Thomas in Cologne 存在两次,我们希望按名称和城市进行分组:

姓名:威尔玛,城市:科隆
姓名:托马斯,城市:科隆
姓名:Lydia,城市:慕尼黑

为什么没有分组?请问我缺少什么?

java java-stream groupingby
1个回答
3
投票

尝试重写

equals
类的
hashcode
PGroup
函数。 尝试用下面的代码替换类代码:

class PGroup {
    final String name;
    final String city;

    public PGroup(String name, String city) {
        this.name = name;
        this.city = city;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PGroup)) return false;
        PGroup pGroup = (PGroup) o;
        return Objects.equals(name, pGroup.name) && Objects.equals(city, pGroup.city);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, city);
    }
}

原因: .equals() 方法的默认实现比较对象引用或对象在堆中存储的内存位置。因此,默认情况下,.equals() 方法使用“==”运算符检查对象。了解有关

equals
hashcode
函数的更多信息 此处

© www.soinside.com 2019 - 2024. All rights reserved.