Как определить несколько функций equals () для класса - PullRequest
4 голосов
/ 26 июня 2010

Я хочу переопределить функцию "public boolean equals (Object obj)" для моего имени и возраста в моем классе с именем 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());

Ответы [ 6 ]

6 голосов
/ 26 июня 2010

Ваш вопрос немного расплывчатый, но если единственная цель состоит в том, чтобы использовать разные алгоритмы сортировки в зависимости от того, какое свойство вы хотите использовать, то лучше использовать 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(), я бы предпочел, чтобы она возвращала значение true, когда оба объекта Person технически или естественно идентичны. Для этого вы можете использовать любой сгенерированный БД ПК для сравнения по технической идентичности:

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;
    }
}

Не забудьте также переопределить hashCode() при переопределении equals().

Смотри также:

3 голосов
/ 26 июня 2010

Я не совсем уверен, к чему вы клоните.Общее ожидание equals () состоит в том, что он возвращает false для null и объектов других классов и выполняет равенство значений в соответствующих полях рассматриваемого класса.

Хотя вы, безусловно, можете обрабатывать String и Integer следующим образом:

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 является отношением эквивалентности , поэтому оно должно быть рефлексивным, симметричным и переходным.Симметричная часть здесь является ключевой, поскольку если a.equals(b), то b.equals(a)String, и Integer не сделают этого за вас.

Если вам нужны только вспомогательные функции, которые проверяют, совпадает ли имя или возраст с данным именем / возрастом, вы можете сделать это.без использования equals():

public boolean equalsName(String name) { return name.equals(this.name); }
public boolean equalsAge(int age) { return age == this.age; }
2 голосов
/ 26 июня 2010

Просто сделайте это коротким и простым (он же KISS принцип): напишите setters и getters .Примерно как в следующем примере:

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();
0 голосов
/ 26 июня 2010
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;
    }

} 
0 голосов
/ 26 июня 2010

Не уверен, что вы подразумеваете под "множественными равными ()".Если вы хотите сравнить оба поля, вам просто нужно переопределить метод 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;
}

Рекомендуется менять hashCode всякий раз, когда вы меняете equals, чтобы HashMap эффективно работал с вашим объектом.

0 голосов
/ 26 июня 2010

если вы хотите переопределить 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
}

Вам необходимо переопределить и hashCode () и equals (), или ни то, ни другое И вы также должны убедиться, что ваш класс final, в противном случае есть потенциальные ловушки с равными .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...