简体   繁体   English

如何在 Java 中正确实现 equals

[英]How to properly implement equals in Java

I need to implement the equals method in some class A. Class A has an orderer collection of Enum type, and the behaviour I want to achive is that equals returns true for two instances of Class A that have exactly the same Enum values in the collection (in exactly the same positions of the collection).我需要在某个类 A 中实现 equals 方法。 A 类有一个 Enum 类型的排序器集合,我想要实现的行为是对于集合中具有完全相同 Enum 值的两个类 A 实例,equals 返回 true (在集合的完全相同的位置)。

As I'm new to java, I'm having problems with this, and I dont know how to properly implement equals or the hashcode methods, so any help would be good :)由于我是 Java 新手,因此遇到了问题,我不知道如何正确实现 equals 或 hashcode 方法,因此任何帮助都会很好:)

If you're using eclipse (netbeans has similar features, as do most java IDEs), you can simply got to the "Source" menu, and choose "Generate hashcode() and equals()".如果您使用的是 Eclipse(netbeans 具有类似的功能,就像大多数 Java IDE 一样),您可以简单地进入“源”菜单,然后选择“生成 hashcode() 和 equals()”。 Then you select the fields you want to be considered (in your case the list of enum values.然后选择要考虑的字段(在您的情况下是枚举值列表。

That being said, assuming you already have the enum, here's the code that eclipse generated for me.话虽如此,假设您已经有了枚举,这里是 eclipse 为我生成的代码。 Not that hashcode usually involves a prime number, as well as multiplication and addition.并不是说哈希码通常涉及素数,以及乘法和加法。 This tends to give you somewhat decent distribution of values.这往往会给你一些体面的值分布。

public class Foo {
   private List<FooEnum> enumValues;

   @Override
   public int hashCode() {
       final int prime = 31;
       int result = 1;
       result = prime * result
               + ((enumValues == null) ? 0 : enumValues.hashCode());
       return result;
   }

   @Override
   public boolean equals(Object obj) {
       if (this == obj)
           return true;
       if (obj == null)
           return false;
       if (getClass() != obj.getClass())
           return false;
       Foo other = (Foo) obj;
       if (enumValues == null) {
           if (other.enumValues != null)
               return false;
       }
       else if (!enumValues.equals(other.enumValues))
           return false;
       return true;
   }


}

The overridden equals method will look like this重写的 equals 方法将如下所示

public boolean equals(Object o) {
    if ((o instanceof yourtype) && 
        (((yourtype)o).getPropertyToTest() == this.propertyToTest)) {
        return true;
    }
    else {
        return false;
    }
}

The overridden hashCode method will look like this重写的 hashCode 方法将如下所示

public int hashCode() { return anIntRepresentingTheHashCode} 

Pulling from the javadocs , your equals method must meet the following criteria:javadocs 中提取,您的 equals 方法必须满足以下条件:

reflexive - x.equals(x) is true自反- x.equals(x) 为真

symmetric - if x.equals(y) then y.equals(x)对称- 如果 x.equals(y) 那么 y.equals(x)

transitive - if x.equals(y) and y.equals(z) then x.equals(z)传递- 如果 x.equals(y) 和 y.equals(z) 那么 x.equals(z)

consistent - if x.equals(y) is true, then it's always true unless the object is modified一致- 如果 x.equals(y) 为真,则除非修改对象,否则它始终为真

null - x.equals(null) is false null - x.equals(null) 为假

Also, if two objects are equal based on the equals method, they must have identical hash codes.此外,如果两个对象基于 equals 方法相等,则它们必须具有相同的哈希码。

The reverse is not true.反过来就不对了。 If two objects are not equal, they may or may not have identical hash codes如果两个对象不相等,则它们可能具有相同的哈希码,也可能不同

Use EnumSet It retains natural order as per java docs also and it is optimized for Enums only.使用EnumSet它也保留了 Java 文档中的自然顺序,并且仅针对 Enum 进行了优化。

The iterator returned by the iteratormethod traverses the elements in their natural order (the order in which the enum constants are declared).迭代器方法返回的迭代器按元素的自然顺序(枚举常量的声明顺序)遍历元素。 The returned iterator is weakly consistent: it will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.返回的迭代器是弱一致性的:它永远不会抛出 ConcurrentModificationException 并且它可能会也可能不会显示在迭代过程中发生的对集合的任何修改的影响。

You can use EnumSet as below您可以使用EnumSet如下

import java.util.EnumSet;

public enum Direction {
LEFT,
RIGHT,
ABOVE,
BELOW;

private static EnumSet<Direction> someDirection = EnumSet.of(Direction.LEFT,Direction.RIGHT) ;
}

Now because you are using EnumSet equals and Hashcode method will be provided default from AbstractSet which is parent class of EnumSet So You don't have to care about them.现在因为您正在使用EnumSet等于和 Hashcode 方法将从AbstractSet提供默认值,它是EnumSet父类,所以您不必关心它们。

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

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