地图中特定键的值总和
Sum of values in the map for specific key
我有一个文本文件,其中的每一行都包含一对名称和数量,如下所示:
Mike 5
Kate 2
Mike 3
我需要按键对这些值求和。我是这样解决的
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
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();
}
;
}
实际上我如何以更实用的方式改进此代码,并能够更并发地处理数据(使用并行流等)
当你想写函数式代码时,规则是:不要使用forEach
。这是一个命令式解决方案,会破坏功能代码。
你想要的是将每一行拆分并按第一部分(键)分组,同时对第二部分(值)求和:
Map<String, Integer> 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
的key,只是returns行的第一部分
downstream
是一个收集器,它减少每个具有相同键的值:在这种情况下,它是 Collectors.summingInt(mapper)
对给定映射器提取的每个整数求和。
作为旁注(如您所知),您可以使用新的 Map.merge(key, value, remappingFunction)
方法更简单地重写整个 forEach
,只需调用:
map.merge(line[0], Integer.valueOf(line[1]), Integer::sum);
如果此键不存在,这将使用键 line[0]
和值 Integer.valueOf(line[1])
放置一个新值,否则,它将使用给定的重新映射函数更新键(这是本例中新旧值之和)。
我有一个文本文件,其中的每一行都包含一对名称和数量,如下所示:
Mike 5
Kate 2
Mike 3
我需要按键对这些值求和。我是这样解决的
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
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();
}
;
}
实际上我如何以更实用的方式改进此代码,并能够更并发地处理数据(使用并行流等)
当你想写函数式代码时,规则是:不要使用forEach
。这是一个命令式解决方案,会破坏功能代码。
你想要的是将每一行拆分并按第一部分(键)分组,同时对第二部分(值)求和:
Map<String, Integer> 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
的key,只是returns行的第一部分downstream
是一个收集器,它减少每个具有相同键的值:在这种情况下,它是Collectors.summingInt(mapper)
对给定映射器提取的每个整数求和。
作为旁注(如您所知),您可以使用新的 Map.merge(key, value, remappingFunction)
方法更简单地重写整个 forEach
,只需调用:
map.merge(line[0], Integer.valueOf(line[1]), Integer::sum);
如果此键不存在,这将使用键 line[0]
和值 Integer.valueOf(line[1])
放置一个新值,否则,它将使用给定的重新映射函数更新键(这是本例中新旧值之和)。