Duplicate key issue with inheritance(equals () )

43 Views Asked by At
@Data
public class Product {

    protected String name;
    protected String systemId;
    protected String productId;
    protected String productPartId;
    protected Pricing pricing;
    protected String productUid;
    protected String productPartUid;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Product product = (Product) o;
        return Objects.equals(systemId, product.systemId) && Objects.equals(productId, product.productId) &&
                Objects.equals(productPartId, product.productPartId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(systemId, productId, productPartId);
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RelatedProduct extends Product {

    private boolean isMandatory;
}

Note: I am partially aware of the dangers of overriding equals() in subclass but it will never be the case for me. The {systemId, productId, productPartId} in the base class will always be the key for both base and extended classes. In other words, even if two RelatedProduct instances are to be compared, I want the base class equals() method to be used.

I tried both the approaches in vain, seems I have made some fundamental mistake.

Approach-1(Desirable): Place both classes in different packages with the Product class fields as private.

Approach-2(Compromise): Place both classes in same packages with the Product class fields as protected.

Code giving error for a field that belongs only to the subclass and is NOT part of the base class equals() :

List<Product> customerProducts = ...;
List<RelatedProduct>relatedProducts = ...;

Map<RelatedProduct, RelatedProduct> conceptRelatedProductsMap = relatedProducts.stream().
                       collect(Collectors.toMap(Function.identity(),Function.identity()));

 customerProducts.forEach(customerProduct -> {

                    Optional<RelatedProduct> conceptProduct = Optional.ofNullable
                            (conceptRelatedProductsMap.get(customerProduct));

                    if (conceptProduct.isPresent()) {
                        //Do something
                    }

Caused by: java.lang.IllegalStateException: Duplicate key RelatedProduct(isMandatory=false) (attempted merging values RelatedProduct(isMandatory=false) and RelatedProduct(isMandatory=false))

Using Approach-2, I tried the below.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RelatedProduct extends Product {

    private boolean isMandatory;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        return super.equals(o);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
}

It got past the duplicate key issue block but it fails to behave expectedly where the subclass object and parent class object are being compared:

conceptRelatedProductsMap.get(customerProduct) //Returns null.
0

There are 0 best solutions below