英文:
Grouping LocalDateTime objects in intervals using Java 8
问题
我有一个以以下格式排列的列表,我想将此列表分成一分钟间隔。
List<Item> myObjList = Arrays.asList(
new Item(LocalDateTime.parse("2020-09-22T00:13:36")),
new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
new Item(LocalDateTime.parse("2020-09-19T00:17:20")));
例如,给定一个间隔为10分钟,列表的前两个对象应在同一组中,第3个应在另一组中,依此类推。
这个列表可以使用Java 8的groupingBy
函数分成间隔吗?
我的解决方案是将列表中的每个日期与列表中的所有其他日期进行比较,并将相差X分钟的日期添加到新列表中。这似乎非常慢且不太正规,我想知道是否有更稳定的解决方案。
英文:
I have a List in the following format and I want to group this List into minute intervals.
List<Item> myObjList = Arrays.asList(
new Item(LocalDateTime.parse("2020-09-22T00:13:36")),
new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
new Item(LocalDateTime.parse("2020-09-19T00:17:20")));
For example, given an interval of 10 minutes the first 2 objects of the list should be in the same group, the 3rd should be in a different group, etc.
Can this List be grouped into intervals using Java's 8 groupingBy
function?
My solution is to compare every date in the list with all the other dates in the list and add the dates that differ X minutes in a new List. This seems to be very slow and 'hacky' workaround and I wonder if there is a more stable solution.
答案1
得分: 6
这里可以使用 Collectors#groupingBy
方法将 LocalDateTime
对象分组为以10分钟为间隔的列表。您需要根据您的 Item
类来调整这个代码片段,但逻辑是相同的。
List<LocalDateTime> myObjList = Arrays.asList(
LocalDateTime.parse("2020-09-22T00:13:36"),
LocalDateTime.parse("2020-09-22T00:17:20"),
LocalDateTime.parse("2020-09-22T01:25:20"),
LocalDateTime.parse("2020-09-18T00:17:20"),
LocalDateTime.parse("2020-09-19T00:17:20")
);
System.out.println(myObjList.stream().collect(Collectors.groupingBy(time -> {
// 存储小时内的分钟字段。
int minutes = time.getMinute();
// 确定我们超过最近的10分钟间隔多少分钟。
int minutesOver = minutes % 10;
// 截断时间到分钟字段(将秒和纳秒清零),
// 并将分钟数强制为10分钟的间隔。
return time.truncatedTo(ChronoUnit.MINUTES).withMinute(minutes - minutesOver);
})));
输出结果:
{
2020-09-22T00:10=[2020-09-22T00:13:36, 2020-09-22T00:17:20],
2020-09-19T00:10=[2020-09-19T00:17:20],
2020-09-18T00:10=[2020-09-18T00:17:20],
2020-09-22T01:20=[2020-09-22T01:25:20]
}
英文:
It is possible to use Collectors#groupingBy
to group LocalDateTime
objects into lists of 10-minute intervals. You'll have to adapt this snippet to work with your Item
class, but the logic is the same.
List<LocalDateTime> myObjList = Arrays.asList(
LocalDateTime.parse("2020-09-22T00:13:36"),
LocalDateTime.parse("2020-09-22T00:17:20"),
LocalDateTime.parse("2020-09-22T01:25:20"),
LocalDateTime.parse("2020-09-18T00:17:20"),
LocalDateTime.parse("2020-09-19T00:17:20")
);
System.out.println(myObjList.stream().collect(Collectors.groupingBy(time -> {
// Store the minute-of-hour field.
int minutes = time.getMinute();
// Determine how many minutes we are above the nearest 10-minute interval.
int minutesOver = minutes % 10;
// Truncate the time to the minute field (zeroing out seconds and nanoseconds),
// and force the number of minutes to be at a 10-minute interval.
return time.truncatedTo(ChronoUnit.MINUTES).withMinute(minutes - minutesOver);
})));
Output
{
2020-09-22T00:10=[2020-09-22T00:13:36, 2020-09-22T00:17:20],
2020-09-19T00:10=[2020-09-19T00:17:20],
2020-09-18T00:10=[2020-09-18T00:17:20],
2020-09-22T01:20=[2020-09-22T01:25:20]
}
答案2
得分: 2
你没有指定分组的关键字,所以我只是使用了(minutes/10)*10
的商来获取分钟范围的起始,并将其附加到截断到小时的时间上。
以下是您提供的代码部分的翻译:
List<Item> myObjList = Arrays.asList(
new Item(LocalDateTime.parse("2020-09-22T00:13:36")),
new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
new Item(LocalDateTime.parse("2020-09-19T00:17:20")));
Map<String, List<Item>> map = myObjList.stream()
.collect(Collectors.groupingBy(item -> {
int range = (item.getTime().getMinute() / 10) * 10;
return item.getTime().truncatedTo(ChronoUnit.HOURS).plusMinutes(range) +
" - " + (range + 9) + ":59";
}));
map.entrySet().forEach(System.out::println);
输出结果为:
2020-09-22T00:10 - 19:59=[2020-09-22T00:13:36, 2020-09-22T00:17:20]
2020-09-19T00:10 - 19:59=[2020-09-19T00:17:20]
2020-09-18T00:10 - 19:59=[2020-09-18T00:17:20]
2020-09-22T01:20 - 29:59=[2020-09-22T01:25:20]
以下是您使用的Item
类:
class Item {
LocalDateTime ldt;
public Item(LocalDateTime ldt) {
this.ldt = ldt;
}
public String toString() {
return ldt.toString();
}
public LocalDateTime getTime() {
return ldt;
}
}
英文:
You didn't specify the key for the groups so I just used the quotient of (minutes/10)*10
to get the start of the range of minutes tagged onto the time truncated to hours.
List<Item> myObjList = Arrays.asList(
new Item(LocalDateTime.parse("2020-09-22T00:13:36")),
new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
new Item(LocalDateTime.parse("2020-09-19T00:17:20")));
Map<String, List<Item>> map = myObjList.stream()
.collect(Collectors.groupingBy(item -> {
int range =
(item.getTime().getMinute() / 10) * 10;
return item.getTime()
.truncatedTo(ChronoUnit.HOURS).plusMinutes(range) +
" - " + (range + 9) + ":59";
}));
map.entrySet().forEach(System.out::println);
Prints
2020-09-22T00:10 - 19:59=[2020-09-22T00:13:36, 2020-09-22T00:17:20]
2020-09-19T00:10 - 19:59=[2020-09-19T00:17:20]
2020-09-18T00:10 - 19:59=[2020-09-18T00:17:20]
2020-09-22T01:20 - 29:59=[2020-09-22T01:25:20]
Here is the class I used.
class Item {
LocalDateTime ldt;
public Item(LocalDateTime ldt) {
this.ldt = ldt;
}
public String toString() {
return ldt.toString();
}
public LocalDateTime getTime() {
return ldt;
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论