当前位置:  开发笔记 > 编程语言 > 正文

特定键的映射中的值的总和

如何解决《特定键的映射中的值的总和》经验,为你挑选了1个好方法。

我有一个文件,文件在每行包含一对名称和金额,如下所示:

Mike 5
Kate 2
Mike 3

我需要按键对这些值求和.我以这种方式解决了这个问题

public static void main(String[] args) {
    Map map = new HashMap();
    try {
        Files.lines(Paths.get("/Users/walter/Desktop/stuff.txt"))
                .map(line -> line.split("\\s+")).forEach(line -> {
                    String key = line[0];
                    if (map.containsKey(key)) {
                        Integer oldValue = map.get(key);
                        map.put(key, oldValue + Integer.parseInt(line[1]));
                    } else {
                        map.put(line[0], Integer.parseInt(line[1]));
                    }
                });
        map.forEach((k,v) -> System.out.println(k + " " +v));

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ;

}

实际上我是如何以更多功能的方式改进这个代码,同时更多地同时处理数据(使用并行流等)



1> Tunaki..:

当您想编写功能代码时,规则是:不要使用forEach.这是一个必不可少的解决方案,并打破功能代码.

你想要的是按第一部分(键)分割每一行和组,同时总结第二部分(值):

Map map = 
    Files.lines(Paths.get("/Users/walter/Desktop/stuff.txt"))
         .map(s -> s.split("\\s+"))
         .collect(groupingBy(a -> a[0], summingInt(a -> Integer.parseInt(a[1]))));

在这段代码中,我们将分割每一行.然后,我们使用以下Collectors.groupingBy(classifier, downstream)位置对Stream进行分组:

classifier,这是一个分类每个项目以提取结果的键的函数Map,只返回行的第一部分

downstream是一个收集器,它减少具有相同键的每个值:在这种情况下,它是Collectors.summingInt(mapper)对给定映射器提取的每个整数求和.


作为旁注(并且你知道),你可以forEach使用新Map.merge(key, value, remappingFunction)方法更简单地重写整个方法,只需调用:

map.merge(line[0], Integer.valueOf(line[1]), Integer::sum);

这将会把一个新值与键line[0]与值Integer.valueOf(line[1]),如果该键不存在,否则,它会更新与给定的重映射功能键(在这种情况下,新旧价值的总和).


@GerardRozsavolgyi我不确定文件中的读取行是否会很好地并行化,但这只是在Stream管道上调用`parallel()`的问题.也许最好收集List中的所有行并在该List上调用`parallelStream()`以按行的第一部分对其进行分组.
推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有