Reputation: 153
Given a java class Something
class Something {
String parent;
String parentName;
String child;
Date at;
int noThings;
Something(String parent, String parentName, String child, Date at, int noThings) {
this.parent = parent;
this.parentName = parentName;
this.child = child;
this.at = at;
this.noThings = noThings;
}
String getParent() { return parent; }
String getChild() { return child; }
int getNoThings() { return noThings; }
}
I have a list of something objects,
List<Something> hrlySomethings = Arrays.asList(
new Something("parent1", "pname1", "child1", new Date("01-May-2015 10:00:00"), 4),
new Something("parent1", "pname1", "child1", new Date("01-May-2015 12:00:00"), 2),
new Something("parent1", "pname1", "child1", new Date("01-May-2015 17:00:00"), 8),
new Something("parent1", "pname1", "child2", new Date("01-May-2015 07:00:00"), 12),
new Something("parent1", "pname1", "child2", new Date("01-May-2015 17:00:00"), 14),
new Something("parent2", "pname2", "child3", new Date("01-May-2015 11:00:00"), 3),
new Something("parent2", "pname2", "child3", new Date("01-May-2015 16:00:00"), 2));
I want to group the objects by parent and children and then find the total/sum of the "noThings" field for the last 24 hours.
List<Something> dailySomethings = Arrays.asList(
new Something("parent1", "pname1", "child1", new Date("01-May-2015 00:00:00"), 14),
new Something("parent1", "pname1", "child2", new Date("01-May-2015 00:00:00"), 26),
new Something("parent2", "pname2", "child3", new Date("01-May-2015 00:00:00"), 5))
I'm trying to use the streams to do this
I can figure out how to use the grouping to get a map of maps, and the total
Map<String,Map<String,IntSummaryStatistics>> daily =
hrlySomethings.stream().collect(
Collectors.groupingBy(Something ::getParent,
Collectors.groupingBy(ClientCollectionsReceived::getChild,
Collectors.summarizingInt(ClientCollectionsReceived::getNoThings))));
I can figure out how to get a distinct list based on parent and child,
Date startHour = "01-May-2015 00:00:00";
int totalNoThings = 0; // don't know how to put sum in here
List<Something> newList
= hrlySomethings.stream()
.map((Something other) -> {
return new Something(other.getParent(),
other.getChild(), startHour, totalNoThings);
})
.distinct()
.collect(Collectors.toList());
But I don't know how to combine the two to get the distinct list, with the totals. Is this possible?
Upvotes: 2
Views: 1421
Reputation: 100169
First I assume that you are using java.util.Date
(though I'd advise you to move to new java.time
API). Second, I assume that Something
class has also properly implemented equals
and hashCode
. Also more getters are necessary:
String getParentName() { return parentName; }
Date getAt() { return at; }
Under these assumptions your task can be solved like this:
List<Something> dailySomethings = hrlySomethings.stream().collect(
Collectors.groupingBy(
smth -> new Something(smth.getParent(),
smth.getParentName(),
smth.getChild(),
new Date(smth.getAt().getYear(),
smth.getAt().getMonth(),
smth.getAt().getDate()),
0),
Collectors.summingInt(Something::getNoThings)
)).entrySet().stream()
.map(entry -> new Something(entry.getKey().getParent(),
entry.getKey().getParentName(),
entry.getKey().getChild(),
entry.getKey().getAt(),
entry.getValue()))
.collect(Collectors.toList());
We use groupingBy
only once, but create a suitable grouping key, which is the Something
with parent
, parentName
and child
set to the original, at
changed to the day beginning and noThings
set to zero. This way you group what you want. If you need only total sums, then summarizingInt
is unnecessary, summingInt
is enough. After that we transform the resulting map to the list creating new Something
objects where noThings
is filled from the map values and the rest is filled from the keys.
Upvotes: 2