gpt4 book ai didi

java - 比较器和一致等于 : How?(最佳实践)

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:04:59 24 4
gpt4 key购买 nike

我知道为了符合 Java 的 Collections 的约定。 (并避免意外行为)任何提供的 Comparator应该和equals一致。

假设我有这样的人:

class Person {
private String name;
private String surname;
private int age;


public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}

public String getName() { return name; }
public String getSurname() { return surname; }
public int getAge() { return age; }
}

比较器是

class PersonComparator implements Comparator<Person> {

@Override
public int compareTo(Person p1, Person p2) {
// throws NPE's
return p1.getName().compareTo(p2.getName());
}
}

现在我想要一些排序的集合( TreeMapSortedSet ,......无论如何),使用 Comparator只比较 Person的名字。该比较器将违反“与平等一致”的约定。但是我不想覆盖 equals(Object o)因为在节目的其他部分,两个人的名字、姓氏和年龄可能不同(就像在现实生活中一样)。

我希望在选定的集合中,名称唯一标识一个人,即 TreeSet<Person>不能有“John Doe”和“John Smith”(同名)。

据我测试,这适用于 Java 集合的当前实现。

我的问题是:您如何“正确”地做到这一点,最好是在不违反任何契约(Contract)的情况下?如果可能的话,我想避免使用第三方库,当然我也不想为了摆脱契约(Contract)而自己实现数据结构。我担心我的代码可能会在未来的 Java 版本中中断,因为它违反了契约(Contract)。

最佳答案

您遇到的问题是 Sets 会忽略重复项。如果你说两个 Person 是相同的,它会将它们视为重复的并删除其中一个。

return p1.getName().compareTo(p2.getName());

因此,如果您有两个名字叫“John”的人,他们将只在 TreeSet 中出现一次。

您需要的是比较您在 equals 中所做的相同字段,例如

int cmp = p1.getName().compareTo(p2.getName());
if (cmp == 0)
cmp = p1.getSurname().compareTo(p2.getSurname());
if (cmp == 0)
cmp = Integer.compare(p1.getAge() - p2.getAge());
return cmp;

这样你只会将两个等于 == true 的人视为重复。

确保具有相同详细信息(但不同)的人不被视为重复的方法是添加唯一 ID,计数器或 UUID。

注意:契约(Contract)不一定是一致的,对于 BigDecimal 来说,它并不完全一致,但在这种情况下,我看不出有什么好的理由希望将 John Smith 和 John Doe 视为同一个人人。

关于java - 比较器和一致等于 : How?(最佳实践),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39891405/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com