2013-07-08 2 views
7

Допустим, у меня есть классJava ArrayList IndexOf - поиск индекса объекта

public class Data{ 
    public int k; 
    public int l; 
    public Data(int k, int l){ 
     this.k = k; 
     this.l = l; 
    } 
    public boolean equals(Date m){ 
     if(this.k == m.k && this.l = m.l) 
      return true; 
     return false; 
    } 
} 

И добавить несколько объектов данных в ArrayList:

ArrayList<Data> holder = new ArrayList<Data>; 
Data one = new Data(0,0); 
Data two = new Data(0,4); 
Data three = new Data(0,5); 

Почему IndexOf не найти это ?:

holder.indexOf(new Data(0,4)); //returns -1 

Действительно ли indexOf лучше всего просматривать весь список массивов? Или я что-то упускаю.

+5

Проблема в том, что вы не переопределяете метод 'equals', а перегружаете. –

ответ

17

полный список. Вот отрывок из Java 7 исходного кода:

public int indexOf(Object o) { 
    if (o == null) { 
     for (int i = 0; i < size; i++) 
      if (elementData[i]==null) 
       return i; 
    } else { 
     for (int i = 0; i < size; i++) 
      if (o.equals(elementData[i])) 
       return i; 
    } 
    return -1; 
} 

Было бы лучше, чтобы пройти через Java, чем написать его самостоятельно. Просто убедитесь, что ваш метод equals достаточен для поиска нужного вам объекта. Вы также захотите переопределить hashCode().

Я не буду писать свой метод equals, но я рекомендовал бы по крайней мере:

  • Проверка на нуль
  • Test, если экземпляры вы сравниваете те же
  • Вы не нужно делать if(boolean_expr) { return true; }; просто верните булево выражение.
  • Убедитесь, что вы фактически переопределяете свой метод equals - для этого требуется параметр Object, а не Date.
-2

По соглашению вы хотите переопределить хэш-код также при перекрытии равно

Вы, скорее всего, обнаружите, что IndexOf использует метод Hashcode, чтобы соответствовать не объект Равных

Если вы используете eclise в отредактируйте код - eclipse создаст хороший метод equals и hashcode для вас из меню «source».

+2

Nope - 'indexOf' использует' equals'. – Makoto

8

Подпись вашего equals метода неверна. Вы не переопределяете equals в Object, а просто перегружаете его.

Чтобы отменить поведение метода equals в Object, ваша подпись должна точно соответствовать таковой в Object. Попробуйте это:

public boolean equals(Object o) { 
    if(!(o instanceof Data)) return false; 
    Data other = (Data) o; 
    return (this.k == other.k && this.l == other.l); 
} 

Кроме того, как другие предположили, что это хорошая идея, чтобы переопределить hashCode метод также для вашего объекта для правильной работы на карте коллекций основе.

2

Ответ от Макото является правильным. То же самое я бы сказал. Но у вас есть некоторые ошибки в вашем коде выше.

  1. Вы написали "public boolean equals (Date m) {". Я думаю, вы имели в виду данные вместо даты.
  2. Вы писали: «if (this.k == m.k & this.l = m.l)». Второе условие в том случае, если запрос должен быть «==».

На ваш вопрос: Ответ Макото - это одно решение. Мое решение заключается в использовании помощи затмения для автоматического создания hashcode и равно методов. Например:

public class Data { 

    // your class code here 

    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + k; 
     result = prime * result + l; 
     return result; 
    } 

    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof Data)) { 
      return false; 
     } 
     Data other = (Data) obj; 
     if (k != other.k) { 
      return false; 
     } 
     if (l != other.l) { 
      return false; 
     } 
     return true; 
    } 
} 
Смежные вопросы