Пользовательский метод Contains ArrayList - PullRequest
29 голосов
/ 30 ноября 2011

У меня есть некоторый объект

class A {
  private Long id; 
  private String name; 
  public boolean equals(Long v) {
     return this.id.equals(v);
  }
}

и ArrayList этих объектов.Я хочу иметь возможность проверить, содержит ли этот список какой-либо объект по полю объекта.Например:

ArrayList<A> list = new ArrayList<A>(); if (list.contains(0L)) {...}

но переопределенный метод Equals мне не помогает.Что я делаю не так?Спасибо

ОБНОВЛЕНИЕ И я должен также переопределить метод hashcode ()?

Ответы [ 3 ]

48 голосов
/ 30 ноября 2011

Вот некоторый код, который может продемонстрировать, как он работает:

import java.util.ArrayList;

class A {
  private Long id; 
  private String name; 

  A(Long id){
      this.id = id;
  }

    @Override
  public boolean equals(Object v) {
        boolean retVal = false;

        if (v instanceof A){
            A ptr = (A) v;
            retVal = ptr.id.longValue() == this.id;
        }

     return retVal;
  }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 17 * hash + (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }
}

public class ArrayList_recap {
    public static void main(String[] args) {
        ArrayList<A> list = new ArrayList<A>(); 

        list.add(new A(0L));
        list.add(new A(1L));

        if (list.contains(new A(0L)))
        {
            System.out.println("Equal");
        }
        else
        {
            System.out.println("Nah.");
        }    
    }

}

Во-первых, существует переопределение метода equals (Object o).Затем есть переопределение hashCode ().Также обратите внимание, что экземпляр A проверки на равенство гарантирует, что вы не пытаетесь сравнивать разные объекты.

Это должно сработать!Надеюсь, это помогло!Приветствия:)

8 голосов
/ 30 ноября 2011

Вы не переопределили метод в своем классе. Для переопределения параметры метода также должны быть одного типа.

должно быть

public boolean equals(Object o) {

}

где, как в вашем случае это

public boolean equals(Long o) {

 }

вам, вероятно, нужно сделать это

public boolean equals(Object o)
    {
        if (o == null) return false;
        if (o == this) return true; //if both pointing towards same object on heap

            A a = (A) o;
        return this.id.equals(a.id);
    }
7 голосов
/ 30 ноября 2011

Что я делаю не так?

Вы не переопределяете. Вы перегружены.

Метод contains вызывает метод equals с подписью equals(Object), поэтому добавленный вами (новый) метод вызываться не будет.

Другая проблема заключается в том, что ваш метод equals имеет неверную семантику для contains. Метод contains должен сравнивать this с объектом, который может быть членом списка. Ваш список не содержит Long объектов. Содержит объекты типа A.

Теперь вам может это сойти с рук ... если вы используете необработанные типы списков ... но то, что вы пытаетесь сделать, это нарушение контракта API и плохая практика. Лучшее решение - явно итерировать и проверять элементы списка.


И мне тоже переопределить метод hashcode ()?

Если вы переопределяете equals(Object), вам также следует переопределить hashcode().

Здесь не будет никакой разницы, но важно, если вы когда-нибудь поместите свои A объекты в хешированные структуры данных. И поскольку вы не знаете, что следующий парень собирается делать с вашим кодом, рекомендуется убедиться, что equals(Object) и hashCode() имеют совместимую семантику.

...