lambda和stream的概念有点弱,因此可能有些东西实际上没有任何意义,但我会尽力传达我想发生的事情。
我有一个发票类,其中有一个项目名称,价格和数量。
我必须将商品名称和总成本(价格*数量)对应起来。
尽管它不起作用,但希望它能使我知道我遇到了什么问题:
invoiceList.stream()
.map(Invoice::getDesc)
.forEach(System.out.println(Invoice::getPrice*Invoice::getQty));
我已经知道forEach不能正常工作,因为它映射到变量description(getDesc),而不是Invoice对象,在这里我可以使用它的方法来获取其他变量。
因此,如果
item=pencil, price=1, qty=12
,我想要的输出是:Pencil 12.00
这将在多个发票对象上完成。
另外,我需要按它们的总数对其进行排序,并且还要过滤超过一定数量的那些,例如。 100.将它们放置在Map中后,我应该怎么做?
最佳答案
如果您只想打印到控制台,则可以按照以下步骤进行操作:
invoiceList.forEach(i -> System.out.println(i.getName() + " " + (i.getPrice() * i.getQty())));
如果没有,请继续阅读:
Using the toMap collector
Map<String, Double> result =
invoiceList.stream()
.collect(Collectors.toMap(Invoice::getName,
e -> e.getPrice() * e.getQuantity()));
这基本上会创建一个映射,其中键是
Invoice
名称,值是给定Invoice
的发票价格和数量的乘积。Using the groupingBy collector
但是,如果可以有多个同名发票,则可以将
groupingBy
收集器与summingDouble
一起用作下游收集器:Map<String, Double> result =
invoiceList.stream()
.collect(groupingBy(Invoice::getName,
Collectors.summingDouble(e -> e.getPrice() * e.getQuantity())));
这按名称对
Invoice
进行分组,然后针对每个组对e.getPrice() * e.getQuantity()
的结果求和。更新:
如果要使用
toMap
版本并过滤结果,然后按值升序排序,可以按以下步骤进行:Map<String, Double> result = invoiceList.stream()
.filter(e -> e.getPrice() * e.getQuantity() > 100)
.sorted(Comparator.comparingDouble(e -> e.getPrice() * e.getQuantity()))
.collect(Collectors.toMap(Invoice::getName,
e -> e.getPrice() * e.getQuantity(),
(left, right) -> left,
LinkedHashMap::new));
或使用
groupingBy
方法: Map<String, Double> result =
invoiceList.stream()
.collect(groupingBy(Invoice::getName,
Collectors.summingDouble(e -> e.getPrice() * e.getQuantity())))
.entrySet()
.stream()
.filter(e -> e.getValue() > 100)
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue, (left, right) -> left,
LinkedHashMap::new));