Java。如何对具有持续时间的对象列表进行分组和减少

问题描述 投票:0回答:1

我想创建一个按 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 java-stream java-time duration localdate
1个回答
0
投票

我发现您熟悉 Java 流 groupingBy API。根据您提供的所需输出,我会尝试以下方法。

首先使用 groupingBy 收集器通过 startDatepersonType 的组合键对人员进行分组。然后,对于每个组,它对持续时间求和并使用求和值创建一个新的 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);
    }
}

如果您需要更多帮助,请告诉我!

祝你好运:)

© www.soinside.com 2019 - 2024. All rights reserved.