重复键的Java 8流和条目

时间:2017-06-25 15:19:39

标签: java java-8 java-stream

我使用Java 8流按特定键对条目列表进行分组,然后按日期对组进行排序。我还想做的是"崩溃"组中任何两个具有相同日期并对其求和的条目。我有一个这样的课程(为了示例目的而被剥离)

class Thing {
    private String key;
    private Date activityDate;
    private float value;
    ...
}

然后我就这样对它们进行分组:

Map<String, List<Thing>> thingsByKey = thingList.stream().collect(
                Collectors.groupingBy(
                        Thing::getKey,
                        TreeMap::new,
                        Collectors.mapping(Function.identity(), toSortedList())
                ));

private static Collector<Thing,?,List<Thing>> toSortedList() {
        return Collectors.collectingAndThen(toList(),
                l -> l.stream().sorted(Comparator.comparing(Thing::getActivityDate)).collect(toList()));
    }

我想要做的是,如果任何两个Thing条目具有完全相同的日期,则总结这些条目的值并将其折叠,以便

Thing1 日期= 1 /二千〇一十七分之一 值= 10

Thing2 日期= 1 /二千〇一十七分之一 值= 20

2017年1月1日变为30。

实现类似目标的最佳途径是什么?

2 个答案:

答案 0 :(得分:4)

我稍稍更改了您的Thing课程以使用LocalData,并添加了一个非常简单的toString

@Override
public String toString() {
   return " value = " + value;
}

如果我理解正确,那么这就是你所需要的:

Map<String, TreeMap<LocalDate, Thing>> result = Arrays
            .asList(new Thing("a", LocalDate.now().minusDays(1), 12f), new Thing("a", LocalDate.now(), 12f), new Thing("a", LocalDate.now(), 13f))
            .stream()
            .collect(Collectors.groupingBy(Thing::getKey,
                    Collectors.toMap(Thing::getActivityDate, Function.identity(),
                            (Thing left, Thing right) -> new Thing(left.getKey(), left.getActivityDate(), left.getValue() + right.getValue()),
                            TreeMap::new)));


 System.out.println(result); // {a={2017-06-24= value = 12.0, 2017-06-25= value = 25.0}}

答案 1 :(得分:2)

这可以使用toMap收集器来完成:

Map<Date, Thing> thingsByDate = things.stream().collect(Collectors.toMap(
    Thing::getActivityDate,
    Function.identity(),
    (thing1, thing2) -> new Thing(null, thing1.getActivityDate(), thing1.getValue()+thing2.getValue())
);

然后您可以根据需要使用此地图。