ArrayList' squash'对其要素的操作

时间:2015-12-19 00:08:41

标签: java loops iterator concurrentmodification

我有一个似乎微不足道的问题,但我正在寻找解决该问题的最佳方法。

我们说我有一个班级:

Product.class

public class Product {
    private int id;
    private String code;
    private String price;
    private String quantity;

    public Product() {}

    //getters and setters

    @Override
    public boolean equals(Object obj) {
        boolean result = false;
        if (obj instanceof ProductOnStockDto) {
            ProductOnStockDto product = (ProductOnStockDto) obj;
            result = (this.code.equals(product.getCode()) && this.price.equals(product.getPrice()));
        }
        return result;
    }
}

让我们说我有一个这个对象的列表:

List<Product> products;

其中填充了this等数据(1行是一个列表元素):

我需要的是迭代这个列表并压缩具有相同代码和相同价格的元素。例如:

在结果列表中,我想为code 3提供两种产品:

code 3 | 1.22 | 11
code 3 | 2.20 | 6

所以我会这样做:

for(Product product : products) {
    for(Product productToSquash : products) {
        if(product.getId() != productToSquash.getId() && product.equals(productToSquash)) {
            //Here I would like to squash these two rows
            //Data conversion is ommited
            product.setQuantity(product.getQuantity() + productToSquash.getQuantity());
            //after that I would like to remove productToSquash object from the collection
        }
    }
}

但据我所知,不允许修改我正在迭代的集合。那么根据示例压缩所有产品列表的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

将它们加载到HashMap中以“挤压”,然后从中加载到新集合

    class Pair
    {
         String code;
         float price;
    }

    HashMap<Pair, Product> hashMap = new HashMap<Pair, Product>();
    List<Product> collection = new ArrayList<Product>(); //a new container for your values

    //for every Product in products
    //    if in hashMap there is no Product with code and price add it
    //    else resolve it (override? ignore? ...)

    for(Entry<Pair, Product> entry : hashMap.values()) {
        collection.add(entry.getValue());
    }

请注意,您必须决定如何压缩元素

答案 1 :(得分:1)

首先,您的equals()方法引用ProductOnStockDto。那应该是Product

要在迭代期间删除元素,请直接使用Iterator,即使用&#34;旧样式&#34; for-loop,并使用Map<Product, Product>来跟踪之前看到的产品。这要求您还实施hashCode()

@Override
public int hashCode()
{
    return this.code.hashCode() * 37 + this.price.hashCode();
}
Map<Product, Product> map = new HashMap<Product, Product>();
for (Iterator<Product> productIter = products.iterator(); productIter.hasNext(); ) {
    Product product = productIter.next();
    Product productToKeep = map.get(product);
    if (productToKeep == null)
        map.put(product, product);
    else {
        productToKeep.setQuantity(productToKeep.getQuantity() + product.getQuantity());
        productIter.remove();
    }
}

你不应该这样做,因为equals()方法正在为真正相等的对象返回true

您应该使用仅codeprice的密钥类,密钥类是需要实现equals()hashCode()的密钥类,而不是{{1 }}