Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove duplicate entries form ArrayList in java

Tags:

I want to remove duplicate entry based on productId and priceTagId. If we remove the duplicates we need to add the quantity

here in productDetails list same productId is there but quantity is different if i need to add the quantity into one

"productDetails" : [
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 2,
            "netQty" : "10mg",
            "priceTagId" : 1,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 4,
            "netQty" : "10mg",
            "priceTagId" : 1,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 6,
            "netQty" : "30mg",
            "priceTagId" : 3,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 8,
            "netQty" : "30mg",
            "priceTagId" : 3,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "2345dfb7d991390e25edf659",
            "quantity" : 8,
            "netQty" : "30mg",
            "priceTagId" : 3,
            "alertAvailablity" : "Success"
        }
    ],

I got final output as

"productDetails" : [
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 6,
            "netQty" : "10mg",
            "priceTagId" : 1,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "5764dfb7d991390e25edff74",
            "quantity" : 14,
            "netQty" : "30mg",
            "priceTagId" : 3,
            "alertAvailablity" : "Success"
        },
        {
            "productId" : "2345dfb7d991390e25edf659",
            "quantity" : 8,
            "netQty" : "30mg",
            "priceTagId" : 3,
            "alertAvailablity" : "Success"
        }

    ],

Based on the productId and priceTagId i need to remove duplicates and add quantity from the removed duplicates entry

private List<ProductDetail> removeDuplicateProducts(List<ProductDetail> productDetails) throws BaseException {
    for (ProductDetail eachProductDetail : productDetails) {
        for (ProductDetail eachInnerProductDetail : productDetails) {
            if(eachProductDetail.getProductId().equals(eachInnerProductDetail.getProductId()))
            {
                if(eachProductDetail.getPriceTagId().equals(eachInnerProductDetail.getPriceTagId()))
                {
                    eachProductDetail.setQuantity(eachProductDetail.getQuantity()+eachInnerProductDetail.getQuantity());
                    productDetails.clear();
                }
            }

        }
    }           
    return productDetails;
}

But i dint get it wy? What wrong?

like image 939
Aravi S Avatar asked Jul 04 '16 10:07

Aravi S


People also ask

Does ArrayList remove duplicates?

Duplicate items can be removed from the ArrayList by using a HashSet as duplicate items are not allowed in a HashSet. So the ArrayList is converted into a HashSet and that removes the duplicate items. Then the HashSet is converted back into an ArrayList.


2 Answers

The most efficient solution is to use a Map where the key is a combination of all the fields you consider to make the products the same and the value contains any additional information.

In your case you could do

private Collection<ProductDetail> accumulateDuplicateProducts(List<ProductDetail> productDetails) {
    // use a map to quickly find entries which match.
    // using a linked HashMap means the order of addition is preserved.
    Map<String, ProductDetail> productMap = new LinkedHashMap<>();
    for (ProductDetail pd : productDetails) {
        // build a composite key of the fields you want to match on.
        String key = pd.getProductId() + " " + pd.getPriceTag();
        // if the Strings match they should be merged.
        // if there was no previous entry, use the current one.
        // if there was a previous entry call merge() to combine them.
        productMap.compute(key, (k, pd2) -> pd2 == null ? pd : merge(pd, pd2));
    }
    return productMap.values();
}

private static ProductDetail merge(ProductDetail pd, ProductDetail pd2) {
    // combine two ProductDetails
}

Note: the time complexity is O(n) instead of O(n^2) if you use two nested loops.

But i dint get it wy? What wrong?

One problem you have is

productDetails.clear();

another problem you have is that you compare every entry against every entry e.g. say you have two entries A and B which match

A is compared with A so A *= 2
A is compared with B do A += B
B is compared with A so B += A
B is compared with B so B *= 2

You still end up with two entries, as you are not removing one.

like image 101
Peter Lawrey Avatar answered Sep 28 '22 02:09

Peter Lawrey


I would create a ProductKey class:

class ProductKey {
  private final Integer productId;
  private final Integer priceTagId;
  //constructor, getters, equals, hashcode
}

Then put all the products in a Map<ProductKey, List<ProductDetail>> where the key is an instance of the class above and the value is the list of all products that match the ProductKey.

Then merge the elements of each list by summing the quantities etc.

You can also probably run those two steps in one go.

like image 28
assylias Avatar answered Sep 28 '22 01:09

assylias