Zion
Zion

Reputation: 753

How does ArrayList index of work?

I can not get this Objects out of a ArrayList I think ArrayList uses the equals method and the hashCode method so I do miss something? This is my Object

public class OPCode {

public String code;

public OPCode(String code){     

    this.code = code;      
}

@Override
public boolean equals(Object o){
 OPCode c = (OPCode) o; 
return this.code.equals(c.code.substring(0, c.code.length()-2)); // returns ture 
}

@Override
public int hashCode() {
   return 1;
}
}

and and example

ArrayList<OPCode> t_codes = new ArrayList();
 OPCode c = new OPCode("1-202");
    t_codes.add(c);
    OPCode e = new OPCode("1-202.0");
    t_codes.indexOf(e); // -1 <-- Problem here 
    t_codes.indexOf(c) // finds it

I want e and c to be equal.

Upvotes: -1

Views: 2212

Answers (6)

Reinaldo Gil
Reinaldo Gil

Reputation: 628

Problem is with your equals method.

return (c.code.equals(code)) || c.code.equals(this.code.substring(0, this.code.length() - 2));

Upvotes: 0

Narmer
Narmer

Reputation: 1454

Your equals() and hashCode() methods are wrong. You are breaking the contract.

If I understood well you want to find the index of e although there is only c in the list, and you want to do so abusing the String#equals() checking equality only for the first 5 letters. So c.code = 1-202, e.code = 1-202.0, doing c.code.equals(e.code.subString(0, e.code.lenght()-2)) should hold true.

This is the correct implementation:

public class OPCode {

    public String code;

    public OPCode(String code){     

        this.code = code;      
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((code == null) ? 0 : code.split("\\.")[0].hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        OPCode other = (OPCode) obj;
        if (code == null) {
            if (other.code != null)
                return false;
        } else{
            String thisCode = code.split("\\.")[0];
            String otherCode = other.code.split("\\.")[0];
            if (!thisCode.equals(otherCode))
                return false;
        }
        return true;
    }
}

Note that I used the method String#split since (and this is my assumption) you want to be equal codes with same numerical part without considering decimal part. Using split we avoid managing variable number of literals.

Test it with:

ArrayList<OPCode> t_codes = new ArrayList<OPCode>();
OPCode c = new OPCode("1-202");
t_codes.add(c);
OPCode e = new OPCode("1-202.0");
System.out.println(t_codes.indexOf(e)); // -1 <-- Problem here now gives 0
System.out.println(t_codes.indexOf(c));

BTW I created both method using eclipse built in function via Source>Generate hashCode() and equals()… and modified for the task.

Upvotes: 2

Petter
Petter

Reputation: 4165

Your equals() method is not commutative. I.e. e.equals(c) != c.equals(e), so it's not unexpected that you get strange behaviour.

Upvotes: 0

codingenious
codingenious

Reputation: 8653

Problem is with your equals method.

t_codes.indexOf(c) is actually referring to object e. Because as per your equals method implementation, e is equal to c, but vice versa is not true.

your e.equals(c) != c.equals(e). You need to revisit equals implementation.

Upvotes: 0

devops
devops

Reputation: 9179

If you are working with Eclipse. Select the method and press F3 (jdk required). Now you will see implementation:

/**
 * Returns the index of the first occurrence of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the lowest index <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
 * or -1 if there is no such index.
 */
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;
}

Upvotes: 0

gprathour
gprathour

Reputation: 15333

You have not added the element to the list t_codes.add(e);

t_codes.indexOf(c) // finds it works because you have added this object to the list t_codes.add(c);

But you have not added your object OPCode e = new OPCode("1-202.0"); to the list. Therefore t_codes.indexOf(e); gives you -1

Upvotes: 0

Related Questions