【问题标题】:Java: Efficient data structure to store object with no 'logical' duplicatesJava:有效的数据结构来存储没有“逻辑”重复的对象
【发布时间】:2016-06-29 14:19:25
【问题描述】:

假设我有一个名为 City 的类,它存储有关城市的一些数据:

public class City {

    String [] states;
    String name;
    double lat, lng;

    //Constructors, getters/setters, etc
}

我想保留一个没有重复的城市列表。现在通常它会很容易(使用 HashSet),但我将比较两个在技术上不同的对象(不同的内存地址)但相同的 String 和 double 值。我希望我的 HashSet 将具有相同内部值的对象视为“等效”。

我似乎无法弄清楚如何做到这一点。我是否覆盖 hashCode() 方法?还是我重写了 equals() 方法?

会像下面这样工作吗?

public int hashCode() {
    return (double) name.hashCode() + lat * 100 + lng;
}

【问题讨论】:

  • 如果你想使用 HashSet,你可以同时覆盖 hashCode 和 equals
  • 你覆盖了这两种方法。
  • 使您的字段最终确定(或至少在逻辑上最终确定)。如果它们是可变的,您最终可能会在 Set 中出现重复项,因为它们在插入时是“唯一的”,但随后不是。

标签: java data-structures hash hashset


【解决方案1】:

只需使用 Set 并为您的班级 City 重新定义这两种方法:

请记住,重新定义 equals 和 hashcode 始终是一个好习惯,如果只重新定义其中一个而不在 HashSetHashMap 等数据结构中出现奇怪的行为,这是不可能的。

注意:Set 是正确的数据结构,因为定义:

不包含重复元素的集合。更正式地说,集合 不包含元素对 e1 和 e2 使得 e1.equals(e2),并且在 最多一个空元素。正如它的名字所暗示的,这个接口模型 数学集合抽象。

【讨论】:

  • Joshua Bloch 的书Effective Java,在第 8 条和第 9 条中彻底讨论了这个主题
【解决方案2】:

在比较equals 中的Stringdouble 值的实际值时,您应该覆盖equalshashCode,并将您的哈希值基于hashCode 方法中的值。

在您展示的实现中,散列可能很弱 - 您可能想要使用素数种子。

当按照建议实施时,equalshashCode 将比较您的对象并根据其成员的值将它们放入存储桶中,这是您通常想要的。

如果您使用的是 IDE(推荐),您可以让 IDE 为您起草这些方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-11
    • 2013-01-14
    • 1970-01-01
    • 2017-01-24
    • 2017-01-28
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多