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?
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.
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.
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.
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.
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());
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With