Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does not ArrayList override equals() for better performance?

Tags:

java

arraylist

ArrayList inherits equals implementation from its parent class AbstractList which is not very effective.

It could first check the size of the two ArrayLists and then return false immediately if these sizes are different. Why does not ArrayList do that?

like image 469
ZhekaKozlov Avatar asked Feb 22 '16 08:02

ZhekaKozlov


People also ask

What happens if we don't override equals method?

You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object. hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.

How can an ArrayList improve performance?

In order to optimize the performance of ArrayLists, it is advisable to set a large enough initial capacity when initializing an ArrayList to incorporate all your data. This will allocate a large enough chunk of memory so that you will probably not need to perform the allocation process again.

What happens if we do not override hashCode () and equals () in HashMap?

If you don't override hashcode() then the default implementation in Object class will be used by collections. This implementation gives different values for different objects, even if they are equal according to the equals() method.

What is the need for overriding equals () method in Java?

Why we override equals() method? It needs to be overridden if we want to check the objects based on the property. For example, we want to check the equality of employee object by the id. Then, we need to override the equals() method.


2 Answers

As noted in this answer, this is not done because some implementations has O(n) complexity of their size method, so this can be indeed a degradation.

I agree that making equals consistent in all lists implementations can affect collections that has O(1) size complexity, but maybe Java developers thought that it's much easier to insert it when you need than removing it when you don't (you'll have to re-implement the whole method!). For example, you can easily add this optimization with something like:

public boolean equals(Object o) {
    // here it is
    if (o instanceof List && this.size() != ((List)o).size())
        return false;

    // call the parent equals
    return super.equals(o);

But if it was originally implemented with the size check (in the abstract class), you had to re-implement the whole method and remove the size check:

public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof List))
        return false;

    ListIterator<E> e1 = listIterator();
    ListIterator<?> e2 = ((List<?>) o).listIterator();
    while (e1.hasNext() && e2.hasNext()) {
        E o1 = e1.next();
        Object o2 = e2.next();
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }
    return !(e1.hasNext() || e2.hasNext());
}
like image 74
Maroun Avatar answered Oct 05 '22 13:10

Maroun


Finally, a decision to override ArrayList.equals() and ArrayList.indexOf() was made: https://bugs.openjdk.java.net/browse/JDK-8196340. Benchmarks show a tangible performance gain.

like image 37
ZhekaKozlov Avatar answered Oct 05 '22 15:10

ZhekaKozlov