【发布时间】:2018-11-22 08:39:27
【问题描述】:
首先,一些上下文代码:
import java.util.*;
import java.util.concurrent.atomic.DoubleAdder;
import java.util.function.Function;
import java.util.stream.Collectors;
class Scratch {
static enum Id {A, B, C}
static class IdWrapper {
private final Id id;
public IdWrapper(Id id) {this.id = id;}
Id getId() { return id; }
}
public static void main(String[] args) {
Map<String, Object> v1 = new HashMap<>();
v1.put("parents", new HashSet<>(Arrays.asList(new IdWrapper(Id.A), new IdWrapper(Id.B))));
v1.put("size", 1d);
Map<String, Object> v2 = new HashMap<>();
v2.put("parents", new HashSet<>(Arrays.asList(new IdWrapper(Id.B), new IdWrapper(Id.C))));
v2.put("size", 2d);
Map<String, Map<String, Object>> allVs = new HashMap<>();
allVs.put("v1", v1);
allVs.put("v2", v2);
上面代表我正在处理的数据结构。我有一个外部映射(键类型无关),其中包含内部“属性映射”作为值。这些内部映射使用字符串来查找不同类型的数据。
在我正在处理的情况下,每个 v1、v2、... 都代表一个“磁盘”。每个磁盘都有特定的大小,但可以有多个父级。
现在我需要将大小 per 父 ID 总结为 Map<Id, Double>。
对于上面的示例,该映射将是 {B=3.0, A=1.0, C=2.0}。
以下代码给出了预期的结果:
HashMap<Id, DoubleAdder> adders = new HashMap<>();
allVs.values().forEach(m -> {
double size = (Double) m.get("size");
Set<IdWrapper> wrappedIds = (Set<IdWrapper>) m.get("parents");
wrappedIds.forEach(w -> adders.computeIfAbsent(w.getId(), a -> new DoubleAdder()).add(size));
});
System.out.println(adders.keySet().stream()
.collect(Collectors.toMap(Function.identity(), key -> adders.get(key).doubleValue())));
但是代码感觉很笨拙(就像我需要第二张地图来增加尺寸一样)。
我有一个类似的情况,总是只有一个父母,这可以很容易地使用
collect(Collectors.groupingBy(...), Collectors.summingDouble(...);
但我为“多个”父母的案子迷路了。
那么,问题:上述计算所需Map<Id, Double> 的转换可以用groupingBy() 重写吗?
仅作记录:以上只是我需要答案的问题的 mcve。我知道“数据布局”可能看起来很奇怪。实际上,例如,我们实际上有代表这些“磁盘”的不同类。但我们的“框架”还允许使用此类 ID 和属性名称访问数据库中任何对象的属性。有时,当您遇到性能问题时,与访问真正的“磁盘”对象本身相比,以这种“原始属性映射”方式获取数据要快几个数量级。换句话说:我不能改变任何关于上下文的东西。我的问题完全是关于重写该计算。
(我受限于 Java8 和“标准”Java 库,但对于较新版本的 Java 或解决此问题的非标准方法的附加答案将不胜感激)
【问题讨论】:
-
在我正在处理的情况下,每个 v1、v2、... 代表一个“磁盘” 然后创建一个具有两个类型属性的 Disk 类,而不是使用 Map .
-
@JBNizet 查看我的更新。以上只是一个例子,实际情况要复杂得多。实际上,使用上述地图方法是有充分理由的(full 查找需要 50 毫秒,而 3 秒......这是一个小配置)
标签: java java-8 java-stream grouping