java - 添加到集合时防止重复

标签 java duplicates addition hashset comparator

情况:

假设我有一个这样的类(class):

class Person {
    public String name;
    public String surname;
    public age;
}

现在我想在一些先前创建的列表(包含一些重复项)的基础上创建一个包含一些人的集合。当然,当我创建集合时,我不想在其中有任何重复项。

HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople);

问题: 让我们假设,在某些情况下,“没有重复项”对我来说意味着“具有不同名称的人”。在其他情况下“不同年龄的人”等。

我看到 HashSetadd 方法使用了 HashMap 中的 put :

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // <== !!
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

问题: 因此,我知道我应该简单地覆盖 Person 中的 equals 并记住为应该“相等”的对象返回相同的 hashCode符合我的要求。但是如果我的“平等”术语在运行时发生变化怎么办?

我这么问,是因为在使用Collections.sort对集合进行排序时,我可以指定一个自定义Comparator,它使我能够根据情况提供比较逻辑。

是否有任何类比机制或您知道的解决方案,使我能够在运行时决定创建一组元素时组件是否相等?

我现在唯一的解决方案是在 Person 类中定义一些静态比较器,然后以使用该比较器的方式重写 equals 方法。然后,通过替换 Person 中的比较器,我实际上改变了等于逻辑......这有意义吗?

最佳答案

The only solution I have now is to define some static Comparator in Person class and then, override an equals method in that way that it uses this comparator

不要那样做。 Comparator 中没有任何内容契约(Contract)要求两个对象在 .equals() 方面不同与非零比较。唯一可以设置的约束是如果两个对象是 .equals()然后相互比较,他们给出 0。 Comparable 的实现然后被称为“与 equals 兼容”。但有些类甚至不尊重 JDK 中的这一点(请参阅 BigDecimal )。

你有两个选择:

  • 使用 SortedSet 。一个TreeSet例如允许您传递 Comparator在运行时。一个SortedSet评估等效性,即两个实例相互比较后给出 0,无论 .equals() 是多少.
  • 如果您使用 Guava,则可以创建一个或多个 Equivalence s 代表您的对象;你的Set然后必须有 Equivalence.Wrapper<Person> 类型的成员而不仅仅是Person你必须 .add(eq.wrap(person)) ,但它确实有效。

关于java - 添加到集合时防止重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22781580/

相关文章:

java - PriorityQueue添加元素会改变元素,奇怪的bug

javascript - 后增量和加法

java - Hadoop:不支持的 major.minor 版本 52.0

java - servlet Controller 中出现空指针异常

batch-file - 计算纯文本文件中与子字符串匹配的行数

r - 重复值子集 >10

php - 如何复制MySQL字段?

c# - 如何使 += 运算符保留对象引用?

java - 将 string[] 转换为逗号分隔的字符串。

java - 如何在 Clojure 中模拟 Java 对象