Search code examples
javaequalscontains

List contains method not work on two different classes with the same attributes


I have these two java classes as below:

RelocationDisabledProduct

public class RelocationDisabledProduct {
    @JsonProperty("productIdentifierType")
    private ProductIdentifierType productIdentifierType;

    @JsonProperty("id")
    private String id;

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        final Item that = (Item)o;
        return Objects.equals(id, that.getId()) &&
            Objects.equals(productIdentifierType, that.getProductIdentifierType());
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, productIdentifierType);
    }
}

Item

public class Item {
    private String id;
    private ProductIdentifierType productIdentifierType;
}

equals works fine

relocationDisabledProduct.equals(item) // true

but contains does not

List<RelocationDisabledProduct> relocationDisabledProducts;
...
getRelocationDisabledProducts().contains(item) // false

Since contains uses the equals method, not sure why my above syntax returns false?


Solution

  • I believe this is due to the definition of AbstractCollection<E> contains(Object o). The Javadoc says

    public boolean contains​(Object o)

    Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that Objects.equals(o, e).

    Note the order of arguments to contains(). It is using the equals() method from Item, not the one from RelocationDisabledProduct, which you would have probably seen if you stepped into the code in the debugger.

    Both Item and RelocationDisabledProduct need to share a common equals() implementation, maybe a default method of a superinterface... you'll have to work out what makes sense in your case.