p1001
p1001

Reputation: 143

Java ArrayList IndexOf - Finding Object Index

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.

Upvotes: 14

Views: 48014

Answers (4)

budo
budo

Reputation: 64

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

Upvotes: 2

Venkat
Venkat

Reputation: 462

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.

Upvotes: 11

Makoto
Makoto

Reputation: 106518

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.

Upvotes: 25

user2480415
user2480415

Reputation: 77

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.

Upvotes: -2

Related Questions