我知道在论坛中也有类似的问题,但是似乎没有一个问题能够完全解决我的问题。现在我对Java 8还是很陌生,所以请多多包涵。我有一个产品列表,例如:
Input:
name category type cost
prod1 cat2 t1 100.23
prod2 cat1 t2 50.23
prod1 cat1 t3 200.23
prod3 cat2 t1 150.23
prod1 cat2 t1 100.23
Output:
Single line (name, category, type) summing the cost and count of products.
Product {
public String name;
public String category;
public String type;
public int id;
public double cost;
}
我需要按名称,类别和类型对其进行分组,并产生一个汇总该数据并得出每个产品的总成本和数量的单个结果。大多数示例显示按两个字段分组并使用单个条件进行汇总。
根据论坛上的建议,我提出了以下分组建议:
public class ObjectKeys {
ArrayList<Object> keys;
public ObjectKeys(Object...searchKeys) {
keys = new ArrayList<Object>();
for (int i = 0; i < searchKeys.length; i++) {
keys.add( searchKeys[i] );
}
}
}
然后按如下方式使用它:
Map<String, Map<String, Map<String, List<Product>>>> productsByNameCategoryType =
products.stream().collect(groupingBy(new ObjectKeys(l.name(), l.category(),l.type())))
但是,如何对上面的代码进行计数和求和?特别适用于具有2个以上字段的分组。有一个更好的方法吗?
就像我提到的Java8那样不好,请帮忙。
class Product {
public String name;
public String category;
public String type;
public int id;
//todo:implement equals(), toString() and hashCode()
}
class Item{
public Product product;
public double cost;
}
您可以使用Collectors#groupingBy和Collectors#summarizingDouble汇总按产品分组的项目。
List<Item> items = ...;
Map<Product, DoubleSummaryStatistics> stat = items.stream().collect(groupingBy(
it -> it.product,
Collectors.summarizingDouble(it -> it.cost)
));
// get some product summarizing
long count = stat.get(product).getCount();
double sum = stat.get(product).getSum();
//list all product summarizing
stat.entrySet().forEach(it ->
System.out.println(String.format("%s - count: %d, total cost: %.2f"
, it.getKey(),it.getValue().getCount(), it.getValue().getSum()));
);
首先,您需要qty
在Item
课程中添加一个字段:
class Item{
public int qty;
//other fields will be omitted
public Item add(Item that) {
if (!Objects.equals(this.product, that.product)) {
throw new IllegalArgumentException("Can't be added items"
+" with diff products!");
}
return from(product, this.cost + that.cost, this.qty + that.qty);
}
private static Item from(Product product, double cost, int qty) {
Item it = new Item();
it.product = product;
it.cost = cost;
it.qty = qty;
return it;
}
}
那么您可以使用Collectors#toMap合并具有相同产品的商品:
Collection<Item> summarized = items.stream().collect(Collectors.toMap(
it -> it.product,
Function.identity(),
Item::add
)).values();
您可以看到两种方法都可以做相同的事情,但是第二种方法更容易在流上进行操作。以及我在github中检查过的两种方法的测试,您可以单击并查看更多详细信息:汇总项目和合并项目的方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句