我想删除基于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;
}
但是我知道吗?怎么了?
答案 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();
您遇到的另一个问题是您将每个条目与每个条目进行比较,例如:假设您有两个匹配
的条目A
和B
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;
}
通过这种方式,您可以拥有原始列表和新列表。