使用流将多个哈希映射的内容相加
Using streams to add up the contents of multiple hashmaps
我有一个 HashMap 矩阵,我正在尝试根据与 "outer" HashMap 的键匹配的给定输入来添加这些 HashMap 的内容。拿下面的SSCCE(有1个error说明我的进度),HashMaps有4行HashMap,我想把第1行和第3行的HashMaps的内容加起来
我当然可以用旧的Java 7 方法来做。但我想用 Java 8 个流来执行此操作而无需迭代。
public class HashMapCollector {
public static void main(String[] args) {
HashMap<Integer, HashMap<Integer, BigDecimal>> map = new HashMap<>();
map.put(1, new LinkedHashMap<>()); // row 1
map.put(2, new LinkedHashMap<>()); // row 2
map.put(3, new LinkedHashMap<>()); // row 3
map.put(4, new LinkedHashMap<>()); // row 4
// row 1
map.get(1).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 2
map.get(2).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 3
map.get(3).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 4
map.get(4).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(4, BigDecimal.TEN, BigDecimal::add);
// Using a HashSet to contain the keys of the rows I want
HashSet<Integer> keys_to_add = new HashSet<>();
keys_to_add.add(1);
keys_to_add.add(3);
// Java 7 boring vanilla iteration
BigDecimal total = BigDecimal.ZERO;
for(Entry<Integer, HashMap<Integer, BigDecimal>> entry : map.entrySet()) {
if(keys_to_add.contains(entry.getKey())) {
for(BigDecimal bd : entry.getValue().values()) {
total = total.add(bd);
}
}
}
System.out.println(total);
// Java 8ish method -- still some boring iteration
total = BigDecimal.ZERO;
for(Entry<Integer, HashMap<Integer, BigDecimal>> entry : map.entrySet()) {
if(keys_to_add.contains(entry.getKey())) {
total = total.add(entry.getValue().values().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
}
}
System.out.println(total);
// Java 8 method -- no iteration
total = BigDecimal.ZERO;
map.entrySet().stream().filter(e -> keys_to_add.contains(e.getKey())).map(Map.Entry::getValue). // This is as far as I got
System.out.println(total);
}
}
我认为从 keys_to_add
开始比遍历所有条目并检查密钥是否在 keys_to_add
中更有意义。
BigDecimal total = keys_to_add.stream()
.filter(map::containsKey)
.map(map::get)
.map(Map::values)
.flatMap(Collection::stream)
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
或者,如果您更喜欢保留垂直方向 space,
BigDecimal total = keys_to_add.stream()
.filter(map::containsKey)
.flatMap(k -> map.get(k).values().stream())
.reduce(BigDecimal.ZERO, BigDecimal::add);
作为您已有内容的延续(因此您可以看到不同之处),您可以这样完成它:
total = map.entrySet()
.stream()
.filter(e -> keys_to_add.contains(e.getKey()))
.map(Map.Entry::getValue)
.map(Map::values)
.flatMap(Collection::stream)
.reduce(BigDecimal.ZERO, BigDecimal::add);
不过我同意 Misha@ 的观点,从 keys_to_add
开始更有意义
我有一个 HashMap 矩阵,我正在尝试根据与 "outer" HashMap 的键匹配的给定输入来添加这些 HashMap 的内容。拿下面的SSCCE(有1个error说明我的进度),HashMaps有4行HashMap,我想把第1行和第3行的HashMaps的内容加起来
我当然可以用旧的Java 7 方法来做。但我想用 Java 8 个流来执行此操作而无需迭代。
public class HashMapCollector {
public static void main(String[] args) {
HashMap<Integer, HashMap<Integer, BigDecimal>> map = new HashMap<>();
map.put(1, new LinkedHashMap<>()); // row 1
map.put(2, new LinkedHashMap<>()); // row 2
map.put(3, new LinkedHashMap<>()); // row 3
map.put(4, new LinkedHashMap<>()); // row 4
// row 1
map.get(1).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(1).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 2
map.get(2).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(2).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 3
map.get(3).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(3).merge(4, BigDecimal.TEN, BigDecimal::add);
// row 4
map.get(4).merge(1, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(2, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(3, BigDecimal.TEN, BigDecimal::add);
map.get(4).merge(4, BigDecimal.TEN, BigDecimal::add);
// Using a HashSet to contain the keys of the rows I want
HashSet<Integer> keys_to_add = new HashSet<>();
keys_to_add.add(1);
keys_to_add.add(3);
// Java 7 boring vanilla iteration
BigDecimal total = BigDecimal.ZERO;
for(Entry<Integer, HashMap<Integer, BigDecimal>> entry : map.entrySet()) {
if(keys_to_add.contains(entry.getKey())) {
for(BigDecimal bd : entry.getValue().values()) {
total = total.add(bd);
}
}
}
System.out.println(total);
// Java 8ish method -- still some boring iteration
total = BigDecimal.ZERO;
for(Entry<Integer, HashMap<Integer, BigDecimal>> entry : map.entrySet()) {
if(keys_to_add.contains(entry.getKey())) {
total = total.add(entry.getValue().values().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
}
}
System.out.println(total);
// Java 8 method -- no iteration
total = BigDecimal.ZERO;
map.entrySet().stream().filter(e -> keys_to_add.contains(e.getKey())).map(Map.Entry::getValue). // This is as far as I got
System.out.println(total);
}
}
我认为从 keys_to_add
开始比遍历所有条目并检查密钥是否在 keys_to_add
中更有意义。
BigDecimal total = keys_to_add.stream()
.filter(map::containsKey)
.map(map::get)
.map(Map::values)
.flatMap(Collection::stream)
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
或者,如果您更喜欢保留垂直方向 space,
BigDecimal total = keys_to_add.stream()
.filter(map::containsKey)
.flatMap(k -> map.get(k).values().stream())
.reduce(BigDecimal.ZERO, BigDecimal::add);
作为您已有内容的延续(因此您可以看到不同之处),您可以这样完成它:
total = map.entrySet()
.stream()
.filter(e -> keys_to_add.contains(e.getKey()))
.map(Map.Entry::getValue)
.map(Map::values)
.flatMap(Collection::stream)
.reduce(BigDecimal.ZERO, BigDecimal::add);
不过我同意 Misha@ 的观点,从 keys_to_add