使用Java 8 Stream API 缩小地图

15

我有一个以下形式的地图:

Map<Integer, Map<String,Double>> START

让INNER成为内部映射,即

Map<String,Double>
例如,我想将START地图缩小为一个新地图。
Map<Integer, Double> END

拥有相同键但不同值的嵌套映射。具体来说,对于每个键,我希望新的Double值是内部映射中相应键的值的总和。

如何使用JAVA 8的STREAM API实现这一目标?

谢谢大家。

编辑:一个样本映射如下:

------------------------------
|      |  2016-10-02   3.45   |
| ID1  |  2016-10-03   1.23   |
|      |  2016-10-04   0.98   |
------------------------------
|      |  2016-10-02   1.00   |
| ID2  |  2016-10-03   2.00   |
|      |  2016-10-04   3.00   |
------------------------------

我希望能获得一张新地图,就像以下这张一样:

--------------------------------
|      |                       |
| ID1  |  SUM(3.45,1.23,0.98)  |
|      |                       |
--------------------------------
|      |                       |
| ID2  |  SUM(1.00,2.00,3.00)  |
|      |                       |
--------------------------------

1
为什么你的内部映射键是字符串?你能提供一个示例映射吗? - Thusitha Thilina Dayaratne
我想使用STREAM API,因为我是新手,需要更好地理解它。 - Fab
你尝试了什么?给我们看看你的代码。 - talex
@talex 关于 Stream API,我还没有编写任何代码。在旧的代码中,我迭代遍历哈希映射,按键逐个执行求和运算。现在,我的目标是通过使用 Stream 来实现相同的结果,而不是手工编写所有代码。 - Fab
@Fab 为什么不尝试自己写呢?如果你总是使用别人为你编写的代码,就永远也学不到任何东西。 - talex
@talex 你说得对。但有时候,一个好的例子是学习任何东西的最佳方式。 - Fab
2个回答

14

它会对你起作用。

    Map<Integer, Double> collect = START.entrySet()
        .stream()
        .collect(
            Collectors.toMap(
                Map.Entry::getKey, 
                e -> e.getValue()
                      .values()
                      .stream()
                      .reduce(0d, (a, b) -> a + b)
                )
        );

1
另一个答案通过流式传输entrySet()而不是keySet()来节省一次查找。 - balki
什么是getValue().values()的含义? - Prabhat Gaur

11

这应该是一个很好的例子:

public class Main {

    public static void main(final String[] args) {
        final Map<Integer, Map<String, Double>> tmp = new HashMap<>();
        tmp.put(1, new HashMap<String, Double>() {{
            put("1", 3.45);
            put("2", 1.23);
            put("3", 0.98);
        }});
        tmp.put(2, new HashMap<String, Double>() {{
            put("1", 1.00);
            put("2", 2.00);
            put("3", 3.00);
        }});

        System.out.println(tmp.entrySet().stream()
                .collect(
                    Collectors.toMap(Map.Entry::getKey, 
                    data -> 
                        data.getValue()
                            .values().stream()
                            .mapToDouble(Number::doubleValue).sum())));
    }

}

输出将是 {1=5.66, 2=6.0} ,这只是获取映射的条目集,获取其流并将内部映射值的总和收集到新映射中。


你的代码给我报了以下错误:方法toMap(Map.Entry::getKey, (<no type> data) -> {})在Start类型中未定义。 - Fab

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