如何在java中从ArrayList中删除重复的条目

时间:2016-07-04 10:11:46

标签: java arraylist

我想删除基于productId和priceTagId的重复条目。如果我们删除重复项,我们需要添加数量

这里的productDetails列表中有相同的productId,但如果我需要将数量添加到一个

,数量会有所不同
"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"
        }
    ],

我得到了最终输出

"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"
        }

    ],

基于productId和priceTagId我需要删除重复项并从删除的重复条目中添加数量

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;
}

但是我知道吗?怎么了?

6 个答案:

答案 0 :(得分:3)

最有效的解决方案是使用Map,其中键是您考虑使产品相同的所有字段的组合,并且值包含任何其他信息。

在你的情况下,你可以做到

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
}

注意:如果使用两个嵌套循环,时间复杂度为O(n)而不是O(n^2)

  

但是我知道吗?怎么了?

你遇到的一个问题是

productDetails.clear();

您遇到的另一个问题是您将每个条目与每个条目进行比较,例如:假设您有两个匹配

的条目AB
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

你仍然有两个条目,因为你没有删除一个。

答案 1 :(得分:1)

我会创建一个ProductKey类:

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

然后将所有产品放在Map<ProductKey, List<ProductDetail>>中,其中键是上面类的实例,值是与ProductKey匹配的所有产品的列表。

然后通过对数量等进行求和来合并每个列表的元素。

您也可以一次运行这两个步骤。

答案 2 :(得分:0)

您可以使用set删除重复项并更改ProductDetail类的equals方法中的数量

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;
    }
}

}

答案 3 :(得分:0)

在这个例子中,我会使用一张地图。让我们看看为什么:

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

相同的方法签名就可以了。现在,差异

//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's 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());

我希望它有所帮助

答案 4 :(得分:0)

在你的代码中,如果你使用“for each”语句,那么列表中的元素总是有一次与自身进行比较,这会得到错误的结果。您应该使用索引来访问列表中的元素

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

并记住使用list.remove(indexOfTheDuplicate)删除重复元素,list.clear()将删除列表中的所有元素。

答案 5 :(得分:0)

您可以更改方法以返回包含所需数据的新列表。

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;
}

通过这种方式,您可以拥有原始列表和新列表。