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 лучше, чем проходить через весь список массивов самостоятельно? Или я что-то упускаю.

4 ответов


на indexOf() метод тут пройдите весь список. Вот выдержка из исходного кода 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 метод, но я бы рекомендовал вам по крайней мере:

  • проверить значение null
  • проверьте, совпадают ли сравниваемые экземпляры
  • вам не нужно делать if(boolean_expr) { return true; }; просто верните логическое выражение.
  • убедитесь, что вы на самом деле переопределение equals метод-подпись этого требует

подпись 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 метод также для вашего объекта для правильной работы в коллекциях на основе карт.


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

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

на ваш вопрос: Ответ Макото-одно из решений. Мое решение-использовать помощь eclipse для автоматической генерации хэш-код и равна методы. Вот так:

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

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

вы, скорее всего, обнаружите, что indexOf использует метод hashcode для соответствия объекту, а не equals

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