Lambdas和Streams(数组)

时间:2018-06-12 16:44:57

标签: java lambda java-8 java-stream

对于lambdas和stream的概念有点弱,所以可能有些东西真的没有任何意义,但我会尝试传达我想要发生的事情。

我有一个班级发票,其中有项目名称,价格和数量。 我必须将项目名称和总成本(价格*数量)映射。

虽然它不起作用,但希望它能让我知道我遇到了什么问题:

invoiceList.stream()
           .map(Invoice::getDesc)
           .forEach(System.out.println(Invoice::getPrice*Invoice::getQty));

我已经可以告诉forEach不能正常工作,因为它映射到变量描述(getDesc)而不是Invoice对象,我可以使用它来获取其他变量。

所以,如果item=pencil, price=1, qty=12,我想要的输出是:

Pencil   12.00

这将在多个Invoice对象上完成。

另外,我需要按总计对它们进行排序,并过滤掉一定数量以上的数据,例如。 100.将它们放入Map后,我该怎么办呢?

2 个答案:

答案 0 :(得分:2)

如果你想要做的只是打印到控制台,那么可以按如下方式完成:

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));

答案 1 :(得分:1)

首先,这是我认为您试图编写的代码:

invoiceList.stream()
       .forEach(invoice -> System.out.println(invoice.getPrice() * invoice.getQty()));

现在让我们来看看这里发生了什么:

在列表中调用.stream()会创建一个对象,该对象具有可用于对列表内容执行操作的方法。 foreach是一种在每个元素上调用函数的方法。 map是另一个这样的方法,但它返回另一个流,其中内容是原始流的内容,但每个元素都被您传递给map的函数的返回值替换。

如果你看一下foreach调用的内部,你可以看到一个lambda。这定义了一个匿名函数,将在invoiceList的每个元素上调用。 invoice符号左侧的->变量绑定到流的每个元素,右侧的表达式执行。