java 如何为类定义多个equals()函数

i2loujxw  于 2023-03-28  发布在  Java
关注(0)|答案(6)|浏览(159)

我想在名为MyObject的类中覆盖“publicboolean equals(Objectobj)”函数,用于name和age,MyObject的结构如下所示

public class MyObject{
       private String name;
       private int age;
}

我怎么能?
@balusC:
这个呢?

vo  = new MyObject() {
                    public boolean equals(Object obj) {
                        return ((MyObject)obj).name().equals(this.getName());

                    }

vo  = new MyObject() {
                    public boolean equals(Object obj) {
                        return ((MyObject)obj).age() == (this.getAge());
sycxhyv7

sycxhyv71#

equals()的一般预期是,它为null和其他类的对象返回false,并对相关类的字段执行值相等。
当然,您可以通过以下方式处理StringInteger

public boolean equals(Object o) {
  if (o == null) return false;
  if (o instanceof String) return name.equals(o);
  if (o instanceof Integer) return ((Integer)o) == age;
  ...
}

这打破了equals的约定,所以你不能这样做(除非事情以非常奇怪的方式出错)。
equals是一个equivalence relation,所以它必须是自反的,对称的和可传递的。这里的对称部分是关键,因为如果a.equals(b),那么b.equals(a)StringInteger都不会为你做这些。
如果你只需要帮助函数来检查名字或年龄是否等于给定的名字/年龄,那么你可以不使用equals()来完成:

public boolean equalsName(String name) { return name.equals(this.name); }
public boolean equalsAge(int age) { return age == this.age; }
mv1qrgav

mv1qrgav2#

保持简短和简单(又名KISS原则):写settersgetters。类似下面的例子:

public class Person {  
  private String name;  
  private int age;  

public String getName() {  
  return name;  
}

public int getAge() {  
  return age;  
}

然后在方法中,你需要做检查,你可以写:

Person person = new Person();
if(person.getName().equals("Something")) doThis();
if(person.getAge() == 1337) doThat();
zzoitvuj

zzoitvuj3#

不知道你说的“多个equals()”是什么意思。如果你想比较两个字段,你只需要像这样覆盖equals方法,

public boolean equals( Object o )
{
    if ( o != null && o instanceof MyObject )
    {
        MyObject m = (MyObject) o;
        if (this.name == null)
            return false;
        return this.name.eqauls(m.name) && this.age == m.age;
    }
    return false;
}

/// Compute a hash code for the pair.
public int hashCode()
{
    int code = name == null ? 0 : name.hashCode();
    return code ^ age;
}

每当更改equals时更改hashCode是一个很好的做法,这样HashMap就可以有效地与对象一起工作。

rta7y2nd

rta7y2nd4#

如果您确实想覆盖equals,它应该看起来像这样:

static private <T> boolean checkEquals(T t1, T t2)
{
   return (t1 == null) ? (t2 == null) : t1.equals(t2);
}
@Override public boolean equals (Object o)
{
   if (o instanceof MyObject)
   {
     MyObject obj = (MyObject)o;
     return checkEquals(this.name, obj.getName()) 
         && this.age == o.getAge();
   }
   else
     return false;
}

@Override public int hashCode() 
{
   // implement hashCode
}

您需要覆盖 both hashCode()和equals()或两者都不覆盖. And you also should make sure your class is final , otherwise there are potential pitfalls with equals

s71maibg

s71maibg5#

public class MyObject { 
    private String name; 
    private int age; 

    @Override
    public boolean equals(Object o){
        if(o instanceof MyObject){
            MyObject otherObject = (MyObject)o;
            if(name == null){
                return otherObject.name == null && otherObject.age == age;
            } else {
                return name.equals(otherObject.name) && otherObject.age == age;
            }
        } else {
            return false;
        }
    }

    // When we overriding equals it is a good practice to override hashCode
    // for consistecy
    @Override
    public int hashCode(){
        int nameCode = (name == null) ? 0 : name.hashCode();
        // See Item 9 in book Effective Java 2nd Edition
        return 31 * nameCode + age;
    }

}
goqiplq2

goqiplq26#

你的问题有点模糊,但如果唯一的目的是根据你想使用的属性有不同的排序算法,那么就使用Comparator

public class Person {
    private String name;
    private int age;

    public static Comparator COMPARE_BY_NAME = new Comparator<Person>() {
        public int compare(Person one, Person other) {
            return one.name.compareTo(other.name);
        }
    }

    public static Comparator COMPARE_BY_AGE = new Comparator<Person>() {
        public int compare(Person one, Person other) {
            return one.age > other.age ? 1
                 : one.age < other.age ? -1
                 : 0; // Maybe compare by name here? I.e. if same age, then order by name instead.
        }
    }

    // Add/generate getters/setters/equals()/hashCode()/toString()
}

您可以按如下方式使用:

List<Person> persons = createItSomehow();

Collections.sort(persons, Person.COMPARE_BY_NAME);
System.out.println(persons); // Ordered by name.

Collections.sort(persons, Person.COMPARE_BY_AGE);
System.out.println(persons); // Ordered by age.

至于实际的equals()实现,当两个Person对象在技术上或本质上相同时,我宁愿让它返回true。您可以使用DB生成的PK来比较技术身份:

public class Person {
    private Long id;

    public boolean equals(Object object) {
        return (object instanceof Person) && (id != null) 
             ? id.equals(((Person) object).id) 
             : (object == this);
    }
}

或者只是比较每一个属性来比较自然身份:

public class Person {
    private String name;
    private int age;

    public boolean equals(Object object) {
        // Basic checks.
        if (object == this) return true;
        if (object == null || getClass() != object.getClass()) return false;

        // Property checks.
        Person other = (Person) object;
        if (name == null ? other.name != null : !name.equals(other.name)) return false;
        if (age != other.age) return false;

        // All passed.
        return true;
    }
}

在覆盖equals()时,不要忘记覆盖hashCode()

另请参见:

相关问题