Java Streams:分组,求和和计数 [英] Java Streams: Grouping, Summing AND Counting
问题描述
我是溪流的新手但对这些可能性非常感兴趣。
I'm new to streams but very intrigued with the possibilities.
我正在尝试编写一个同时进行分组,计数和求和的流。所涉及的数据实际上非常简单,但编写我需要的流式语句证明具有挑战性,而且我没有看到任何真正有用的谷歌搜索。
I'm trying to write a stream that does grouping, counting and summing at the same time. The data involved is actually quite simple but writing the streaming statement I need is proving challenging and I'm not seeing anything really helpful in Google searches.
首先,让我来描述一下我的数据,然后我会告诉你我是如何解决问题的三分之二。也许你可以告诉我如何适应缺失的部分。
First, let me describe my data, then I'll show you how I've solved two-thirds of the problem. Perhaps you can tell me how to fit in the missing piece.
数据是销售音乐会门票的公司的门票销售。每笔销售包括代理商代码,订单号,订单日期和售出的门票数量。因此,它看起来像这样:
The data is ticket sales from a company that sells concert tickets. Each sale consists of an agency code, an order number, order date and the number of tickets sold. Therefore, it looks like this:
AgencyCode OrderNumber OrderDate TicketsSold
---------- ----------- --------- -----------
TW 111111 2016-03-01 4
TW 111112 2016-03-01 2
CP 201000 2016-03-01 3
TW 111113 2016-03-01 8
CP 201001 2016-03-02 2
EL 300001 2016-03-01 4
AS 400000 2016-03-02 2
我想要的是什么这些数据中的摘要显示了每个代理商代码的总订单数以及同一代理商代码的销售总票数。因此,我想要获取此特定数据集的值为:
What I'm trying to get out of this data is a summary showing the total number of orders for each agency code and the total number of tickets sold for that same agency code. Therefore, the values I want to get for this particular set of data is:
AgencyCode Orders TicketsSold
TW 3 14
CP 2 5
EL 1 4
AS 1 2
我已经完成了分组工作以及售出的门票数量。这只是我想要获得的订单的计数。
I've got the grouping working and also the number of tickets sold. It's just the counting of the orders that I'm trying to get.
这是我如何获得代理商出售的门票:
Here's how I got the tickets sold by agency:
Map<String, Integer> salesByAgency
= ticketOrders.stream()
.collect(Collectors.groupingBy(TicketSale::getAgencyCode,
Collectors.summingInt(TicketSale::getTicketsSold)));
TicketSale
是持有单个的类门票订单。我的收藏 ticketOrders
,是一个 LinkedHashSet
,持有一堆 TicketSale
记录。
TicketSale
is the class that holds a single ticket order. My collection, ticketOrders
, is a LinkedHashSet
holding a bunch of TicketSale
records.
如何调整每个代理商代码的订单数量?
How do I adjust what I have to get the number of orders for each agency code?
推荐答案
你可以使用
Map<String, Integer> orders = ticketOrders
.stream()
.collect(Collectors.groupingBy(TicketSale::getAgencyCode,
Collectors.summingInt(x -> 1)));
或
Map<String, Long> orders = ticketOrders
.stream()
.collect(Collectors.groupingBy(TicketSale::getAgencyCode,
Collectors.counting()));
按代理商获取订单数量。
to get the number of orders by agency.
如果你想同时对计数和订单进行分组,你必须定义自己的收集器,例如
If you want to group count and orders simultaneously you have to define your own collector, e.g.
Map<String, int[]> grouped = ticketOrders
.stream()
.collect(Collectors.groupingBy(TicketSale::getAgencyCode,
Collector.of(
() -> new int[2],
(a, t) -> { a[0] += 1; a[1] += t.getTicketsSold(); },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; })));
然而,这种贬义可能很难理解。 : - )
However, this kind of lambdaism might be hard to understand. :-)
[edit]
在这种情况下,收集器由三部分组成。
第一行是供应商,它创建一个新的结果容器,在这种情况下是一个包含两个元素的数组:一个用于计数,一个用于总和。
第二行是累加器;它将数据添加到现有结果容器中。
第三行是 combiner ,用于将两个结果容器合并为一个。
[edit] The collector is composed of three parts in this case. The first line is the supplier that creates a new result container, in this case an array with two elements: one for the count, one for the sum. The second line is the accumulator; it adds data to an existing result container. The third line is the combiner that is used to merge two result containers into one.
有关详细说明,您可以,一如既往,请参阅 Java API文档。
For a detailed explanation you might, as always, consult the Java API documentation.
这篇关于Java Streams:分组,求和和计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!