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
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?
The simplest solution would be to use
Collectors.summarizingInt()
:The
IntSummaryStatistics
class maintains count, sum, min and max values. So after this you can get the sum for some group:But you can also get the count:
You can use
or
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.
However, this kind of lambdaism might be hard to understand. :-)
[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.
For a detailed explanation you might, as always, consult the Java API documentation.