How to remove duplicate entries from ArrayList in java

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

here in productDetails list the same productId is, but the quantity is different if I need to add the quantity to 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 the final result 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 productId and priceTagId, I need to remove duplicates and add quantity from deleted duplicates record

 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 understand that this is so? What's wrong?

+5
source share
6 answers

The most effective solution is to use the Card, where the key is a combination of all the fields that you think are necessary to make the products the same, and the value contains any additional information.

In your case, you can 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 understand that this is so? What's wrong?

You have one problem:

 productDetails.clear(); 

Another problem is that you are comparing each record with each record, for example. let's say you have two entries A and B that correspond

 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 have two entries, since you are not deleting them.

+3
source

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 Map<ProductKey, List<ProductDetail>> , where the key is an instance of the class above and the value is a list of all products matching the ProductKey.

Then combine the elements of each list by adding up the quantities, etc.

You can also run these two steps at a time.

+1
source

You can use set to remove duplicates and change the quantity in the equals method of the ProductDetail class

 import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class Test { public static void main(String[] args) { List<ProductDetail> productDetails = new ArrayList<ProductDetail>(); ProductDetail p1 = new ProductDetail("1", "pt1", 10); ProductDetail p2 = new ProductDetail("1", "pt1", 40); ProductDetail p3 = new ProductDetail("2", "pt1", 30); productDetails.add(p1); productDetails.add(p2); productDetails.add(p3); List<ProductDetail> list = removeDuplicateProducts(productDetails); for (ProductDetail p : list) { System.out.println(p); } } private static List<ProductDetail> removeDuplicateProducts( List<ProductDetail> productDetails) { Set<ProductDetail> set = new LinkedHashSet<ProductDetail>( productDetails); List<ProductDetail> list = new ArrayList<ProductDetail>(); list.addAll(set); return list; } private static class ProductDetail { public ProductDetail(String productId, String priceTagId, int quantity) { this.productId = productId; this.priceTagId = priceTagId; this.quantity = quantity; } String productId; String priceTagId; int quantity; public String getProductId() { return productId; } public void setProductId(String productId) { this.productId = productId; } public String getPriceTagId() { return priceTagId; } public void setPriceTagId(String priceTagId) { this.priceTagId = priceTagId; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } @Override public String toString() { return (this.productId+"--"+this.priceTagId+"--"+this.quantity); } @Override public int hashCode() { return (this.priceTagId.hashCode()*this.priceTagId.hashCode()); } @Override public boolean equals(Object obj) { ProductDetail p1 = (ProductDetail) obj; if ((p1.getPriceTagId().equals(this.getPriceTagId()) && p1 .getProductId().equals(this.getProductId()))) { p1.setQuantity(this.getQuantity() + p1.getQuantity()); return true; } return false; } } 

}

0
source

In this example, I would use a map. Let's see why:

 private List<ProductDetail> removeDuplicateProducts(List<ProductDetail> productDetails) throws BaseException { 

The same method signature will be fine. Now the difference

 //This map will contain the final set of elements Map<Integer, ProductDetail> map = new HashMap<Integer, ProductDetail>(); for (ProductDetail item: productDetails){ //If map already contains the same productId it adds the quantities but doesn't add the same productId again if(map.containsKey(item.getProductId())){ ProductDetail mapItem = map.get(item.getProductId()); mapItem.setQuantity(mapItem.getQuantity() + item.getQuantity()); } //If map doesn't contain the same productId, it added for the first time else{ mapItem.put(item.getProductId(), item); } } //At this point the map only contains a set of different productId. Now it will be dumped into a list and returned. return new ArrayList<String>(map.values()); 

I hope this helps

0
source

In your code, if you use the so-called "for each", the list item always has one time when it is compared with itself, and this will give the wrong result. You must use an index to access list items.

 for (int i = 0; i <= list.size() - 1; i++) { for (int j = i + 1; j <= list.size() - 1; j++) { <enter your if statements here> } } 

and rememeber to remove the duplicate element using list.remove (indexOfTheDuplicate), list.clear () will delete all the elements of the list.

0
source

You can change the approach to return a new list with the necessary data.

 private List<ProductDetail> removeDuplicateProducts(List<ProductDetail> productDetails) { List<ProductDetail> returnList = new ArrayList<ProductDetail>(); boolean exists = false; for (ProductDetail eachProductDetail : productDetails) { exists = false; for (ProductDetail eachInnerProductDetail : returnList) { // Your match condition if (eachProductDetail.getProductId().equals(eachInnerProductDetail.getProductId()) && eachProductDetail.getPriceTagId().equals(eachInnerProductDetail.getPriceTagId()) ) { exists = true; eachInnerProductDetail.setQuantity(eachProductDetail.getQuantity() + eachInnerProductDetail.getQuantity()); break; } } // add to output list if not exists if (!exists){ returnList.add(eachProductDetail); } } return returnList; } 

This way you can have an original list and a new one.

0
source

All Articles