简体   繁体   English

如果我的类在Java中实现可比性,我是否需要equals和Hashcode方法?

[英]Do I need a equals and Hashcode method if my class implements comparable in Java?

I found this comment on can StringBuffer objects be keys in TreeSet in Java? 我发现这个注释可以将StringBuffer对象作为Java中TreeSet中的键吗?

"There are 2 identifying strategies used with Maps in Java (more-or-less). “在Java中使用地图有两种识别策略(或多或少)。

Hashing: An input "Foo" is converted into a best-as-possible attempt to generate a number that uniquely accesses an index into an array. 散列:输入“Foo”被转换为尽可能最好的尝试,以生成唯一访问数组索引的数字。 (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. “Foo”和“Bar”实际上可能生成相同的索引值,这意味着它们都将映射到相同的数组位置。 Obviously this can't work and so that's where the "equals()" method comes in; 显然这不起作用,所以这就是“equals()”方法的用武之地; 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". “Foo”等于的唯一关键是“Foo”。 A really good idea though is if you can is to define "equals()" as compareTo() == 0; 一个非常好的想法是,如果你可以将“equals()”定义为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. 我的问题如下:如果我的类实现了可比性,那么它是否意味着我不必重写equals和hashcode方法来将我的对象用作Hash集合中的键。 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? 现在,我可以在Hashable集合中使用我的Person对象吗?

The article you brough is talking on TreeSet . 你通过的文章是在TreeSet上讨论的。 a tree set is a tree with each node has a place defined by it's value in compare to the other values already in the tree. 树集是一棵树,每个节点都有一个由它的值定义的位置,与树中已有的其他值相比较。

a hashTable stores key/value pairs in a hash table. hashTable将键/值对存储在哈希表中。 When using a Hashtable, you specify an object that is used as a key, and the value that you want linked to that key. 使用Hashtable时,您可以指定用作键的对象,以及要链接到该键的值。 The key is then hashed, and the resulting hash code is used as the index at which the value is stored within the table. 然后对密钥进行散列,并将得到的散列代码用作值存储在表中的索引。

the difference between Hashable and TreeSet is that treeset don't need hashCode , it just need to know if you need the take the item left or right in the tree. HashableTreeSet之间的区别在于Hashable集不需要hashCode ,它只需要知道你是否需要在树中左右移动项目。 for that you can use Compare and nothing more. 为此你可以使用比较而已。

in hashTable a compare will suffice, because it's build differently, each object get to his cell by hashing it, not by comparing it to the items already in the collection. 在hashTable中,比较就足够了,因为它的构建方式不同,每个对象都通过对其进行散列来到达他的单元格,而不是通过将其与集合中已有的项目进行比较。

so the answer is no, you can' use Person in hashtable just with compareTo . 所以答案是否定的,你可以'使用compareTo Person in hashtable。 u must override hashCode() and equals() for that 你必须覆盖hashCode()equals()

i also suggest you read this article on hashtables 我还建议你阅读关于哈希表的这篇文章

HashTable does use equals and hashCode. HashTable确实使用equals和hashCode。 Every class has those methods. 每个班级都有这些方法。 If you don't implement them, you inherit them. 如果您不实现它们,则继承它们。

Whether you need to implement them depends on whether the inherited version is suitable for your purposes. 是否需要实现它们取决于继承的版本是否适合您的目的。 In particular, since Person has no specified superclass, it inherits the Object methods. 特别是,由于Person没有指定的超类,因此它继承了Object方法。 That means a Person object is equal only to itself. 这意味着Person对象仅与其自身相等。

Do you need two distinct Person objects to be treated as being equal as HashTable keys? 您是否需要将两个不同的Person对象视为与HashTable键相等?

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. 如果我的类实现了可比性,那么它是否意味着我不必重写equals和hashcode方法来将我的对象用作Hash集合中的键。 eg 例如

No, you still need to implement equals() and hashCode() . 不,您仍然需要实现equals()hashCode() The methods perform very different functions and cannot be replaced by compareTo() . 这些方法执行非常不同的功能,不能被compareTo()替换。

  • equals() returns a boolean based on equality of the object. equals()根据对象的相等性返回一个布尔值。 This is usually identity equality and not field equality. 这通常是身份平等而不是字段平等。 This can be very different from the fields used to compare an object in compareTo(...) although if it makes sense for the entity, the equals() method can be: 这可能与用于比较compareTo(...)的对象的字段非常不同,尽管如果它对实体有意义,则equals()方法可以是:

     @Overrides public boolean equals(Object obj) { if (obj == null || obj.getClass() != getClass()) { return false; } else { return compareTo((Person)obj) == 0; } } 
  • hashCode() returns an integer value for the instance which is used in hash tables to calculate the bucket it should be placed in. There is no equivalent way to get this value out of compareTo(...) . hashCode()返回实例的一个整数值,该值在哈希表中用于计算它应该放入的存储桶。没有相同的方法可以从compareTo(...)获取该值。

TreeSet needs Comparable, to add values to right or left of tree. TreeSet需要Comparable,以便在树的右侧或左侧添加值。 HashMap needs equals() and Hashcode() methods that are available from Object Class but you have to override them for your purpose. HashMap需要可从Object Class获得的equals()和Hashcode()方法,但您必须为了您的目的而重写它们。

If a class implements Comparable , that would suggest that instances of the class represent values of some sort; 如果一个类实现了Comparable ,那么表明该类的实例代表某种类型的值; generally, when classes encapsulate values it will be possible for there to exist two distinct instances which hold the same value and should consequently be considered equivalent. 通常,当类封装值时,可能存在两个不同的实例,它们保持相同的值,因此应该被认为是等价的。 Since the only way for distinct object instances to be considered equivalent is for them to override equals and hashCode , that would imply that things which implement Comparable should override equals and hashCode unless the encapsulated values upon which compare operates will be globally unique (implying that distinct instances should never be considered equivalent). 因为不同对象实例被认为是等价的唯一方法是它们覆盖equalshashCode ,这意味着实现Comparable东西应该覆盖equalshashCode 除非 compare操作的封装值将是全局唯一的(暗示不同)实例永远不应被认为是等价的)。

As a simple example, suppose a class includes a CreationRank field of type long ; 举个简单的例子,假设一个类包含一个long类型的CreationRank字段; every time an instances is created, that member is set to a value fetched from a singleton AtomicLong , and Comparable uses that field to rank objects in the order of creation. 每次创建实例时,该成员都设置为从单个AtomicLong获取的值, Comparable使用该字段按创建顺序对对象进行排序。 No two distinct instances of the class will ever report the same CreationRank ; 没有两个不同的类实例会报告相同的CreationRank ; consequently, the only way x.equals(y) should ever be true is if x and y refer to the same object instance--exactly the way the default equals and hashCode work. 因此, x.equals(y)应该为真的唯一方法是xy引用相同的对象实例 - 完全是默认equalshashCode工作的方式。

BTW, having x.compare(y) return zero should generally imply that x.equals(y) will return true, and vice versa, but there are some cases where x.equals(y) may be false but x.compare(y) should nonetheless return zero. 顺便说一句,让x.compare(y)返回零通常意味着x.equals(y)将返回true,反之亦然,但在某些情况下x.equals(y)可能为false但x.compare(y)仍应返回零。 This may be the case when an object encapsulates some properties that can be ranked and others that cannot. 当一个对象封装一些可以排序的属性而另一些不能排序时,可能就是这种情况。 Consider, for example, a hypohetical FutureAction type which encapsulates a DateTime and an implementation of a DoSomething interface. 例如,考虑一种低级FutureAction类型,它封装了DateTimeDoSomething接口的实现。 Such things could be ranked based upon the encapsulated date and time, but there may be no sensible way to rank two items which have the same date and time but different actions. 这些事情可以根据封装的日期和时间进行排名,但可能没有明智的方法来排列具有相同日期和时间但行动不同的两个项目。 Having equals report false while compare reports zero would make more sense than pretending that the clearly-non-equivalent items should be called "equal". equals报告为false而compare报告为零比假装明显不相等的项目应该被称为“相等”更有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM