Java - 列表中每个重复订单的汇总订单数量

Java - Rollup Order quanity for each duplicate order in a list

使用下面提供的代码,我想要实现的是: 我有订单进来,如果列表中有相同产品的订单 - 按产品名称标识,我必须增加第一个订单的数量并删除其他类似订单。

下表中类似订单的示例:P3 和 P4。

但是这种方法会导致异常,想知道你们是否可以建议任何其他方法。

这是一个示例列表,我的列表通常包含 800 个或更多订单。

public class RollUpLogic {

public static void main(String[] args) {
    List<Order> orderList = new ArrayList<Order>();
    orderList.add(new Order("P1", 1));
    orderList.add(new Order("P2", 1));
    orderList.add(new Order("P3", 1));
    orderList.add(new Order("P3", 1));
    orderList.add(new Order("P3", 1));
    orderList.add(new Order("P4", 1));
    orderList.add(new Order("P4", 2));


    //if same product ordered, Rollup the quantity and remove duplicate orders

        Iterator<Order> iterator = orderList.iterator();
        while(iterator.hasNext()) {
            Order order = iterator.next();
            int firstIndex = orderList.indexOf(order);
            int lastIndex = orderList.lastIndexOf(order);
            while(firstIndex!=lastIndex) {
                //+1 qty of firstindex order
                order.setProductQTY(order.getProductQTY()+1);

                //remove order at lastIndex
                orderList.remove(lastIndex); //throws concurrent modification exception
               lastIndex = orderList.lastIndexOf(order);
            }
        }
}
}


class Order{
private String productName;
private int productQTY;

public Order(String productName, int productQTY) {
    super();
    this.productName = productName;
    this.productQTY = productQTY;
}

public int getProductQTY() {
    return productQTY;
}
public void setProductQTY(int productQTY) {
    this.productQTY = productQTY;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((productName == null) ? 0 : productName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Order other = (Order) obj;
    if (productName == null && other.productName != null) {
            return false;
    } else if (!productName.equals(other.productName))
        return false;
    return true;
}   
}

我建议您创建另一个包含分组订单的列表。 这对内存来说不是什么大问题,因为您将添加引用。

您可以简单地创建一个新列表,而不用修改现有列表。迭代集合时不能使用 Collection.remove(或 add 等),这就是导致异常的原因。

为了提高效率,您可以使用 LinkedHashMap

LinkedHashMap<Order> orderMap = new LinkedHashMap<Order>();
for (Order order: orderList) {
    String orderName = order.getProductName();
    if (orderMap.containsKey(orderName)) {
        Order existing = orderMap.get(orderName);
        existing.setProductQty(existing.getProductQty() + order.getProductQty());
    } else {
        orderMap.put(orderName, order);
    }
}

// optionally, copy back to the list
orderList.clear();
for (Order order: orderMap.values()) {
    orderList.add(order);
}

您尝试实现的基本上是一个从 String (productName) 到 int (quantity) 的 MultiMap。为什么不使用一个(例如 guava has a nice general implementation, or you could use a trove TObjectIntHashMap 及其 adjustOrPutValue 方法)?

您还可以在 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html

中使用一些并发实现

使用 Map<String, Integer>,您可以在其中跟踪每个产品名称的商品数量:

Map<String, Integer> productQuantity = new HashMap<>();
for(Order o : orderList) {
    Integer q = productQuantity.get(o.getProductName());
    int newQ = o.getProductQTY() + (q == null ? 0 : q.intValue());
    productQuantity.put(o.getProductName(), newQ);
}

然后您可以将此地图转换为更新订单的“列表”。