我有一个<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "http://www.example.com/",
"contactPoint": [{
"@type": "ContactPoint",
"telephone": "+1-401-555-1212",
"contactType": "customer service"
}]
}
</script>
的集合,以前是使用流分组的。 Map<Pair<DateTime, String>, List<Entity>>
是一个包含Entity
属性和int
方法的简单类。
现在,我希望将getValue()
的值与我的简单Entity
的用法进行汇总,将前一张地图的类型设置为EntityAccumulator
。根据我的理解,实现这一目标的唯一方法是创建我自己的自定义收藏家,但我仍然坚持Map<Pair<DateTime, String>, EntityAccumulator>
方法应该返回finisher()
。
或者,也许有更简单的方法来实现我想要的结果?
StreamProcessing
Pair
EntityAccumulator
Map<Pair<DateTime, String>, EntityAccumulator> collect = entities.stream()
.collect(Collectors.groupingBy(entity-> Pair.of(entity.getTimestamp(), entity.getName())))
.entrySet().stream()
.collect(new EntityCollector()));
集电极
private static class EntityAccumulator {
private int result = 0.0;
public EntityAccumulator() { }
public EntityAccumulator(int result) {
this.result = result;
}
public void calculate(Entity entity) {
result += entity.getValue();
}
public EntityAccumulatoradd(EntityAccumulator other) {
return new EntityAccumulator(this.result + other.result);
}
}
答案 0 :(得分:5)
显然,你真的想做
Map<Pair<DateTime, String>, Double> collect = entities.stream()
.collect(Collectors.groupingBy(
entity -> Pair.of(entity.getTimestamp(), entity.getName()),
Collectors.summingDouble(Entity::getValue)));
或
Map<Pair<DateTime, String>, Integer> collect = entities.stream()
.collect(Collectors.groupingBy(
entity -> Pair.of(entity.getTimestamp(), entity.getName()),
Collectors.summingInt(Entity::getValue)));
取决于实际值类型。您的声明int result = 0.0
不太清楚。
首先,如果要对组执行缩减,则应将值Collector
作为groupingBy
collector的第二个参数提供。然后,它不必同时处理Map
和Map.Entry
。
由于它基本上将实体折叠为单个数字(对于每个组),因此您可以使用现有的收集器,即summingInt
或summingDouble
。
创建自己的收集器时,无法在已在累加器功能中删除的装订器功能中重建信息。如果您的容器类型EntityAccumulator
仅包含一个数字,则无法从中生成Map.Entry<Pair<DateTime, String>, EntityAccumulator>
。
顺便说一下,即使在创建自定义收集器时,也很少需要使用类实现Collector
接口。您只需使用Collector.of
,指定功能和特征,即可创建Collector
。
因此,使用原来的EntityAccumulator
课程(假设result
应为int
而0.0
是拼写错误),您可以使用
Map<Pair<DateTime, String>, Integer> collect = entities.stream()
.collect(Collectors.groupingBy(
entity -> Pair.of(entity.getTimestamp(), entity.getName()),
Collector.of(EntityAccumulator::new,
EntityAccumulator::calculate,
EntityAccumulator::add,
ea -> ea.result,
Collector.Characteristics.UNORDERED)));
实现与上述相同。也可以通过两个步骤执行操作,例如尝试使用
Map<Pair<DateTime, String>, Integer> collect = entities.stream()
.collect(Collectors.groupingBy(e -> Pair.of(e.getTimestamp(), e.getName())))
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream().collect(
Collector.of(EntityAccumulator::new,
EntityAccumulator::calculate,
EntityAccumulator::add,
ea -> ea.result,
Collector.Characteristics.UNORDERED))));
但是,当然,这只是为了完整性。本答案开头显示的解决方案更简单,更有效。