我想使用 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,城市:慕尼黑
为什么没有分组?请问我缺少什么?
尝试重写
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
函数的更多信息 此处