Java ArrayList IndexOf - Finding Object Index

◇◆丶佛笑我妖孽 提交于 2019-12-17 16:07:21

问题


Lets say I have a class

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

And I add a few Data objects to a 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);

Why does indexOf not find this?:

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

Is indexOf any better than going through the whole array list myself? Or am I missing something.


回答1:


The indexOf() method does go through the entire list. Here's an excerpt from Java 7 source code:

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

It'd be better to let Java go through it than write it yourself. Just make sure that your equals method is sufficient at finding the object you want. You'll also want to override hashCode() as well.

I won't write your equals method out, but I would recommend that you at least:

  • Check for null
  • Test if the instances you're comparing are the same
  • You don't need to do if(boolean_expr) { return true; }; just return the boolean expression.
  • Make sure you're actually overriding your equals method - the signature of that requires an Object parameter, not Date.



回答2:


The signature of your equals method is wrong. You are not overriding the equals in Object, but just overloading it.

To override the behavior of equals method in Object, your signature must exactly match with the one in Object. Try this:

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

In addition, as others suggested, it is a good idea to override hashCode method also for your object to work correctly in map based collections.




回答3:


The answer from Makoto is right. The same i would say to. But you have some mistakes in your code above.

  1. You wrote "public boolean equals(Date m){". I think, you meant Data instead of Date.
  2. You wrote "if(this.k == m.k && this.l = m.l)". The second condition in if query have to be "==".

To your question: Makoto's answer is one solution. My solution is to use the help of eclipse to auto generate hashcode and equals methods. Like this:

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



回答4:


By convention you want to override hashcode also when you override equals

You will most probably find that the indexOf uses the hashcode method to match the object not the equals

If you use eclise to edit you code - eclipse will generate a good equals and hashcode method for you from the "source" menu.



来源:https://stackoverflow.com/questions/17519019/java-arraylist-indexof-finding-object-index

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!