views:

170

answers:

4

When you call remove(object o) on an arraylist in java, how does it compare the objects to find the correct one to remove? does it use the pointer? or does it compare the objects using the interface Comparable?

+1  A: 

The docs answer your question:

Removes a single instance of the specified element from this collection, if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if the collection contains one or more such elements.

leonbloy
+1  A: 

It uses equals()

from the docs:

Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists). Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call).

YGL
+1  A: 

ArrayList remove() relies on the objects implementation of the Equal method. If no implementation has been done then the object is removed by Object's implementation of Equals which indeed is the pointer comparison.

From the documentation on ArrayList -

More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists)

Object equal method documentation -

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Eric U.
+1  A: 

You should always consult the API for this kind of information.

ArrayList.remove(Object o): Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged. More formally, removes the element with the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists).

Perhaps you were confusing this with e.g. TreeSet:

java.util.TreeSet: Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal.

(Unfortunately e.g. TreeSet.remove method itself doesn't have any explicit reminder of the above caveat, but at least it's prominently placed at the top of the class documentation)


An illustrative example

The following snippet illustrates the difference in behaviors between collections that use equals (such as an ArrayList) and collections that use compare/compareTo (such as a TreeSet).

import java.util.*;

public class CollectionEqualsCompareTo {
    static void test(Collection<Object> col, Object o) {
        col.clear();
        col.add(o);
        System.out.printf("%b %b %b %b%n",
            col.contains(o),
            col.remove(o),
            col.contains(o),
            col.isEmpty()
        );
    }
    public static void main(String[] args) {
        Object broken1 = new Comparable<Object>() {
            // Contract violations!!! Only used for illustration!
            @Override public boolean equals(Object o)    { return true; }
            @Override public int compareTo(Object other) { return -1;   }
        };
        Object broken2 = new Comparable<Object>() {
            // Contract violations!!! Only used for illustration!
            @Override public boolean equals(Object o)    { return false; }
            @Override public int compareTo(Object other) { return 0;     }
        };
        test(new ArrayList<Object>(), broken1); // true true false true
        test(new TreeSet<Object>(),   broken1); // false false false false
        test(new ArrayList<Object>(), broken2); // false false false false
        test(new TreeSet<Object>(),   broken2); // true true false true
    }
}
polygenelubricants