如何使用Java 8中的Lambda迭代一个Map嵌套Map?

10

我对Java和lambda都很新,我想在一个地图的地图中找到值的总和和平均值。

我的对象如下:Map<String, Map<String, Double>> browserData;

数据格式为:

<Chrome, <UK, 2.90>>
<Chrome, <US, 5.20>>
<Chrome, <EU, -0.25>>
<IE, <UK, 0.1>>
<IE, <US, -.20>>
<IE, <EU, 0.00>>
<FF, <UK, 0.90>>
<FF, <US, 1.20>>
<FF, <EU, 1.25>>

最终结果需要两张地图,一张显示总和,另一张显示平均值。

map1 = <CountryName, SumValue>

map2 = <CountryName, AverageValue>

因此,上述示例的结果将是:

map1 = <UK, 3.9>
       <US, 6.2>
       <EU, 1>

map2 = <UK, 1.3>
       <US, 2.07>
       <EU, 0.33>

我该如何实现这个目标?


3
请提供您尝试过的代码。否则,这个问题看起来像是一个“给我代码”的问题。 - jww
1个回答

8

这个想法是要流式处理内部映射的每个条目,并应用适当的收集器来计算您需要的值:

Map<String, DoubleSummaryStatistics> stats = browserData.values().stream()
        .flatMap(m -> m.entrySet().stream()) //Stream the inner maps' entrySets
        .collect(groupingBy(Entry::getKey, summarizingDouble(Entry::getValue)));
DoubleSummaryStatistics ds = stats.getOrDefault("EU", new DoubleSummaryStatistics());
System.out.println("sumEu = " + ds.getSum());
System.out.println("avgEu = " + ds.getAverage());

如果您确实需要单独的总和和平均数地图,您可以从汇总地图创建它们。
Map<String, Double> map1 = stats.entrySet().stream()
        .collect(toMap(Entry::getKey, e -> e.getValue().getSum()));
Map<String, Double> map2 = stats.entrySet().stream()
        .collect(toMap(Entry::getKey, e -> e.getValue().getAverage()));

注意:我使用了以下静态导入:
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summarizingDouble;
import static java.util.stream.Collectors.toMap;

在这段代码中,我们使用了Java 8中的流支持库。通过静态导入三个函数,我们可以使用其中的方法来将一些对象进行分组、求和或转换为一个Map。这些函数可以使代码更加简洁易读,减少了冗余的代码,提高了开发效率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接