我想创建一个按 LocalDate 和 String 排序并按持续时间聚合的人员列表。
我做了一些关于流中持续时间的使用的研究: 如何使用 java 流 API 获取每个类别的电影的平均持续时间 在 Java 中使用流对不可变的“Duration”对象集合求和 以及使用流将对象列表分组和减少为子组: 在 Java 8 中对对象列表进行分组并将子组减少为不同的对象
但是,我不可能解决我的问题,班上的人是这样的:
class Person {
private LocalDate startDate;
private String personType;
private Duration time1;
private Duration time2;//constructor, getter+setter, other methods
}
创建的列表的示例如下所示:
List<Person> personList = Arrays.asList(
new Item("2023-02-02","member1","08:00","4:00"),
new Item("2023-02-02","member1","50:00","0:45"),
new Item("2023-02-02","member2","10:00","0:40"),
new Item("2023-02-02","member2","01:00","1:20"),
new Item("2023-02-03","member1","08:00","2:00"),
new Item("2023-02-03","member1","10:00","0:45"),
new Item("2023-02-03","member2","10:00","1:40"),
new Item("2023-02-03","member2","02:00","1:20"),//...
);
现在我想创建一个按开始日期和人员类型排序的人员列表,以及持续时间的总和。
所需输出:
("2023-02-02","member1","58:00","4:45"),
("2023-02-02","member2","11:00","2:00"),
("2023-02-03","member1","18:00","2:45"),
("2023-02-03","member2","12:00","3:00"),
...
我的方法是使用这样的东西。但是,我无法映射持续时间和字符串值:
Map<LocalDate,List<Person>> result=personList.stream()
.collect(Collectors.groupingBy(Person::getstartDate))
.entrySet().stream()
.collect(Collectors.toMap(x -> {
//how to sum duration values in here?
// Duration duration1 = x.getValue().stream() ...;
//how to use String values in here?
// String string = x.getValue().stream()....
return new Person(x.getKey(), string, duration1,duration2);
}, Map.Entry::getValue));
我发现您熟悉 Java 流 groupingBy API。根据您提供的所需输出,我会尝试以下方法。
首先使用 groupingBy 收集器通过 startDate 和 personType 的组合键对人员进行分组。然后,对于每个组,它对持续时间求和并使用求和值创建一个新的 Person 对象。最后,将生成的 Person 对象收集到一个列表中。 Person.java 类中的代码应该是这样的:
class Person {
.
.
.
public static Person sumDurationsAndTypes(List<Person> persons) {
LocalDate startDate = persons.get(0).getStartDate();
String personType = persons.get(0).getPersonType();
Duration sumTime1 = Duration.ZERO;
Duration sumTime2 = Duration.ZERO;
for (Person person : persons) {
sumTime1 = sumTime1.plus(person.getTime1());
sumTime2 = sumTime2.plus(person.getTime2());
}
return new Person(startDate, personType, sumTime1, sumTime2);
}
@Override
public String toString() {
return "(" + startDate + "," + personType + "," + formatDuration(time1) + "," + formatDuration(time2) + ")";
}
private String formatDuration(Duration duration) {
long hours = duration.toHours();
long minutes = duration.minusHours(hours).toMinutes();
return String.format("%02d:%02d", hours, minutes);
}
sumDurationsAndTypes 方法计算每个人员组的持续时间总和,toString 方法格式化持续时间以进行打印。
然后您可以使用它来检查一切是否按您想要的方式工作:
public class Main {
public static void main(String[] args) {
List<Person> personList = Arrays.asList(
new Person(LocalDate.parse("2023-02-02"), "member1", Duration.ofHours(8), Duration.ofMinutes(4)),
// Add more persons here...
);
Map<String, List<Person>> grouped = personList.stream()
.collect(Collectors.groupingBy(person -> person.getStartDate() + person.getPersonType()));
List<Person> resultList = grouped.values().stream()
.map(Person::sumDurationsAndTypes)
.collect(Collectors.toList());
resultList.forEach(System.out::println);
}
}
如果您需要更多帮助,请告诉我!
祝你好运:)