6

I found this comment on can StringBuffer objects be keys in TreeSet in Java?

"There are 2 identifying strategies used with Maps in Java (more-or-less).

Hashing: An input "Foo" is converted into a best-as-possible attempt to generate a number that uniquely accesses an index into an array. (Purists, please don't abuse me, I am intentionally simplifying). This index is where your value is stored. There is the likely possibility that "Foo" and "Bar" actually generate the same index value meaning they would both be mapped to the same array position. Obviously this can't work and so that's where the "equals()" method comes in; it is used to disambiguate

Comparison: By using a comparative method you don't need this extra disambiguation step because comparison NEVER produces this collision in the first place. The only key that "Foo" is equal to is "Foo". A really good idea though is if you can is to define "equals()" as compareTo() == 0; for consistency sake. Not a requirement."

my question is as follows: if my class implements comparable, then does it mean I dont have to override equals and hashcode method for using my objects as keys in Hash collections. eg

class Person implements Comparable<Person> {
     int id;
     String name;

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

    public int compareTo(Person other) {
      return this.id-other.id;
    }
}

Now, can I use my Person objects in Hashable collections?

4

5 回答 5

6

你带来的文章正在谈论TreeSet。树集是一棵树,与树中已有的其他值相比,每个节点都有一个由它的值定义的位置。

ahashTable将键/值对存储在哈希表中。使用 Hashtable 时,您指定一个用作键的对象,以及要链接到该键的值。然后对键进行哈希处理,生成的哈希码用作值存储在表中的索引。

Hashable和之间的区别在于TreeSettreeset 不需要hashCode,它只需要知道您是否需要在树中向左或向右取项目。为此,您可以使用比较,仅此而已。

在 hashTable 中进行比较就足够了,因为它的构建方式不同,每个对象通过散列它而不是通过将其与集合中已有的项目进行比较来到达他的单元格。

所以答案是否定的,你不能Person在哈希表中使用compareTo. 你必须覆盖hashCode()equals()为此

我还建议你阅读这篇关于哈希表的文章

于 2013-08-22T23:49:55.493 回答
2

HashTable 确实使用 equals 和 hashCode。每个类都有这些方法。如果你不实现它们,你就会继承它们。

是否需要实现它们取决于继承的版本是否适合您的目的。特别是,由于 Person 没有指定的超类,它继承了 Object 方法。这意味着 Person 对象仅与自身相等。

您是否需要将两个不同的 Person 对象视为等同于 HashTable 键?

于 2013-08-22T23:59:18.767 回答
1

如果我的类实现了可比较,那么这是否意味着我不必重写 equals 和 hashcode 方法来使用我的对象作为 Hash 集合中的键。例如

不,您仍然需要实现equals()and hashCode()。这些方法执行的功能非常不同,不能用compareTo().

  • equals()根据对象的相等性返回一个布尔值。这通常是身份平等而不是字段平等。这可能与用于比较对象的字段非常不同,compareTo(...)尽管如果它对实体有意义,则该equals()方法可以是:

    @Overrides
    public boolean equals(Object obj) {
         if (obj == null || obj.getClass() != getClass()) {
            return false;
         } else {
             return compareTo((Person)obj) == 0;
         }
    }
    
  • hashCode()返回实例的整数值,该值在哈希表中用于计算应放置的存储桶。没有等效的方法可以从compareTo(...).

于 2013-08-22T23:56:10.087 回答
0

如果一个类实现了Comparable,那将表明该类的实例代表某种类型的值;通常,当类封装值时,可能存在两个不同的实例,它们持有相同的值,因此应该被认为是等价的。由于不同对象实例被视为等效的唯一方法是让它们覆盖equalsand hashCode,这意味着实现的事物Comparable应该覆盖equals并且hashCode 除非操作所依据的封装值compare将是全局唯一的(这意味着永远不应将不同的实例视为等效的)。

举个简单的例子,假设一个类包含一个CreationRank类型为 的字段long;每次创建实例时,该成员都会设置为从单例中获取的值AtomicLong,并Comparable使用该字段按创建顺序对对象进行排名。没有两个不同的类实例会报告相同的CreationRank;因此,唯一的方法x.equals(y)应该是正确的,如果xy引用同一个对象实例——这正是默认equalshashCode工作的方式。

顺便说一句,x.compare(y)返回零通常意味着x.equals(y)将返回 true,反之亦然,但在某些情况下x.equals(y)可能为 false,但x.compare(y)仍应返回零。当一个对象封装了一些可以排名而其他不能排名的属性时,可能会出现这种情况。例如,考虑一个封装接口和实现的假设FutureAction类型。可以根据封装的日期和时间对此类事物进行排名,但是可能没有明智的方法来对日期和时间相同但动作不同的两个项目进行排名。在报告为零时报告错误比假装明显不等效的项目应该被称为“相等”更有意义。DateTimeDoSomethingequalscompare

于 2013-08-23T21:08:14.783 回答
0

TreeSet 需要 Comparable,用于向树的右侧或左侧添加值。HashMap 需要 Object Class 提供的 equals() 和 Hashcode() 方法,但您必须根据需要重写它们。

于 2013-08-23T01:47:49.760 回答