Reputation: 71
I've the list in the following format:
int intervalInMinutes = 10;
String startTimeForGrouping = "2017-05-09T15:37:51.896+00:00";
List<MyObject> myObjList = Arrays.asList(
new MyObject("1","a","2017-05-09T15:38:51.896+00:00"),
new MyObject("1","a","2017-05-09T16:41:51.896+00:00"),
new MyObject("1","a","2017-05-09T16:49:51.896+00:00"),
new MyObject("1","a","2017-05-09T16:51:51.896+00:00"),
new MyObject("2","b","2017-05-09T17:38:51.896+00:00"),
new MyObject("2","b","2017-05-09T18:41:51.896+00:00")
);
I've got the list in the above format: I wanted to iterate through that and perform some grouping with an interval from given start time and achieve as follows: In the above list, the group id 1 should return 2 lists.
First 2 objects in the single list because its in the first interval from startTimeForGrouping ("2017-05-09T15:37:51.896+00:00" + intervalInMinutes (10)).
3rd and 4th in a different list because that comes in the next interval ("2017-05-09T15:47:51.896+00:00" + intervalInMinutes (10)). The same logic should repeat for id 2 as well
I have tried this
Map<String, Map<Long, List<MyObject>>> aggrResult =
myObjList.stream()
.collect(
Collectors.groupingBy(
MyObject::getId,
Collectors.groupingBy(eachQueueObj -> eachQueueObj.getIntervalStartTime()/interval)));
but this is wrong because I want to aggregate based on the interval from the given start time.
Please help me since am new to java streaming
Upvotes: 3
Views: 649
Reputation: 81
I think the code is that,you could try and remodify the getTime method to fix your need
package com.test;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
*
*
*
*
*
* @author shikai.liu
* @version 1.0
* @since JDK1.7
*/
public class TestList {
public static String strDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
public static SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
public static class MyObject {
public String id;
public String code;
public String time;
public MyObject(String id, String code, String time) {
this.code = code;
this.id = id;
this.time = time;
}
public String getId() {
return this.id;
}
public String getIntervalStartTime() {
return time;
}
public long getTime(Integer t, String srcTime) {
long result = 0;
try {
Date dstDate = sdf.parse(time);
Date srcDate = sdf.parse(srcTime);
long inteval = dstDate.getTime() - srcDate.getTime();
result = inteval / (1000 * 60) / t;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
public static void main(String[] args) throws Exception {
int intervalInMinutes = 10;
String startTimeForGrouping = "2017-05-09T15:37:51.896+00:00";
List<MyObject> myObjList = Arrays.asList(new MyObject("1", "a", "2017-05-09T15:38:51.896+00:00"), new MyObject("1", "a",
"2017-05-09T16:41:51.896+00:00"), new MyObject("1", "a", "2017-05-09T16:49:51.896+00:00"), new MyObject("1", "a",
"2017-05-09T16:51:51.896+00:00"), new MyObject("2", "b", "2017-05-09T17:38:51.896+00:00"), new MyObject("2", "b",
"2017-05-09T18:41:51.896+00:00"));
Map<String, Map<Long, List<MyObject>>> aggrResult = myObjList.stream().collect(
Collectors.groupingBy(MyObject::getId, Collectors.groupingBy(a -> a.getTime(intervalInMinutes, startTimeForGrouping))));
System.out.println(1);
}
}
Upvotes: 1
Reputation: 271810
You should parse the date strings into Instant
objects, and call Duration.between
to get a duration. Then, divide that duration by intervalInMinutes
minutes. Finally, multiply this number by intervalInMinutes
and add that to startTimeForGrouping
to get the grouping key.
Before the stream operation, parse startTimeForGrouping
to an instant, and make a Duration
from startTimeForGrouping
:
Instant startInstant = OffsetDateTime.parse(startTimeForGrouping).toInstant();
Duration interval = Duration.ofMinutes(startTimeForGrouping);
Then you can declare a method roundInstant
:
public static Instant roundInstant(Instant instant, Duration interval, Instant start) {
long multiple =
Duration.between(start, instant)
.getSeconds() / interval.getSeconds();
return start.plus(interval.multipliedBy(multiple));
}
The second groupingBy
call can then look like this:
Collectors.groupingBy(
eachQueueObj -> roundInstant(
OffsetDateTime.parse(eachQueueObj.getIntervalStartTime()).toInstant(),
interval,
startInstant
).getEpochSecond()
)
In fact, I would recommend you to not use String
s and Long
s, and work with Instant
s directly.
Upvotes: 3