php editor Strawberry brings you questions and answers about grouping streams by 3 fields and aggregating the other two fields by the sum in Java 8. In Java programming, streams are a new way of processing collections. By using streams, data can be manipulated and processed more conveniently. This article will introduce in detail how to use the stream function of Java 8 to group by 3 fields and perform sum aggregation on the other two fields. Let’s explore this interesting question together!
I am new to java 8 and am having difficulty implementing the solutions that have been provided on similar questions. please help.
In java 8, how to group by three fields that returns multiple rows that must be summed over the remaining two integer fields. In the dto/pojo class below, the incoming count and outgoing count fields need to be summed based on the unique key of the uuid, msgdate, and channel combination.
public class reportdata { private string uuid; private string msgdate; private string channel; private integer incomingcount; private integer outgoingcount; }
//Initialization list as an example.
List<ReportData> list1 = new ArrayList<>(); list1.add(new ReportData("c9c3a519","December 2023", "digital", 5, 0 )); list1.add(new ReportData("c9c3a519","December 2023", "digital", 3, 0 )); list1.add(new ReportData("c9c3a519","December 2023", "digital", 0, 3 )); list1.add(new ReportData("c9c3a519","November 2023", "digital", 4, 0 )); list1.add(new ReportData("c9c3a519","November 2023", "digital", 0, 4 )); list1.add(new ReportData("c9c3a519","December 2023", "manual", 5, 0 )); list1.add(new ReportData("c9c3a519","December 2023", "manual", 3, 0 )); list1.add(new ReportData("c9c3a519","December 2023", "manual", 0, 3 )); list1.add(new ReportData("c9c3a519","November 2023", "manual", 4, 0 )); list1.add(new ReportData("c9c3a519","November 2023", "manual", 0, 4 )); list1.add(new ReportData("3de4c44f","December 2023", "digital", 5, 0 )); list1.add(new ReportData("3de4c44f","December 2023", "digital", 0, 3 )); list1.add(new ReportData("3de4c44f","November 2023", "digital", 4, 0 )); list1.add(new ReportData("3de4c44f","November 2023", "digital", 0, 4 )); list1.add(new ReportData("3de4c44f","December 2023", "manual", 5, 0 )); list1.add(new ReportData("3de4c44f","December 2023", "manual", 0, 3 )); list1.add(new ReportData("3de4c44f","November 2023", "manual", 4, 0 )); list1.add(new ReportData("3de4c44f","November 2023", "manual", 0, 4 ));
The output object should contain the following data:
uuid msgdate Channel incoming count outgoing count
c9c3a519 December 2023 Number 8 3
c9c3a519 November 2023 Number 4 4
c9c3a519 December 2023 Manual 8 3
c9c3a519 November 2023 Manual 4 4
...
...
...
Collect the results into a map. This example will use Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapFactory).
Also, for the sake of brevity, I use lombok annotations.
First create classes to represent the keys and aggregated data to be grouped:
@allargsconstructor @getter public class count { private final int in; private final int out; public count merge(count other) { return new count(this.in + other.in, this.out + other.out); } @override public string tostring() { return in + " " + out; } }
@allargsconstructor public class key { private final string uuid; private final string date; private final string channel; @override public int hashcode() { return objects.hash(uuid, date, channel); } @override public boolean equals(object obj) { if (this == obj) { return true; } if (!(obj instanceof key)) { return false; } key other = (key) obj; return uuid.equals(other.uuid) && date.equals(other.date) && channel.equals(other.channel); } @override public string tostring() { return uuid + " " + date + " " + channel; } }
Then extend reportdata
with 2 more methods to create the key and initial aggregation:
@allargsconstructor public class reportdata { //the fields public key createkey() { return new key(uuid, msgdate, channel); } public count createcount() { return new count(incomingcount, outgoingcount); } }
and collect data:
public class somain { public static void main(string[] args) { list<reportdata> list = new arraylist<>(); //populate the list map<key, count> result = list.stream() .collect(collectors.tomap(reportdata::createkey, reportdata::createcount, count::merge, linkedhashmap::new)); for (map.entry<key, count> entry : result.entryset()) { system.out.println(entry.getkey() + " " + entry.getvalue()); } } }
The parameters of the collector are as follows:
reportdata::createkey
- Create the key to group by (key of the map)reportdata::createcount
- Creates an initial aggregate from a single
reportdatacount::merge
- Merge two count
(see merge method) linkedhashmap::new
- Factory for map
used to insert results. I want to preserve the insertion order, but if not needed, the parameter can be omitted to use the default factory. Print:
c9c3a519 December 2023 digital 8 3 c9c3a519 November 2023 digital 4 4 c9c3a519 December 2023 manual 8 3 c9c3a519 November 2023 manual 4 4 3de4c44f December 2023 digital 5 3 3de4c44f November 2023 digital 4 4 3de4c44f December 2023 manual 5 3 3de4c44f November 2023 manual 4 4
The above is the detailed content of Java 8 stream group by 3 fields and aggregate other two fields by sum. For more information, please follow other related articles on the PHP Chinese website!