如何合并两个com.google.common.collect.Table并对重复键值求和?
刚好之前处理过类似的Guava Table合并需求,给你两种靠谱的实现方式,完全匹配你要的「相同行键+列键时对应值相加」的需求:
解决方案:合并Guava Table并累加重复键的值
这里假设你使用的是Guava库中的Table接口(比如HashBasedTable实现类),下面分别提供Java 8 Stream的优雅写法,以及更直观的传统迭代写法。
Java 8 Stream 实现方式
我们可以把两个Table的所有单元格(Cell)转成流合并,通过复合键分组后累加值,最后再转回Table结构。这里用AbstractMap.SimpleEntry来封装行键+列键作为复合键,它天然实现了equals和hashCode,可以直接作为Map的键使用。
import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import com.google.common.collect.Table.Cell; import java.util.AbstractMap; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class TableMergeStreamExample { public static void main(String[] args) { // 初始化示例数据 Table<Long, String, Integer> tableOne = HashBasedTable.create(); tableOne.put(1L, "Fruits", 20); tableOne.put(2L, "Fruits", 30); tableOne.put(2L, "Vegetables", 15); tableOne.put(3L, "Vegetables", 10); Table<Long, String, Integer> tableTwo = HashBasedTable.create(); tableTwo.put(2L, "Fruits", 10); tableTwo.put(2L, "Vegetables", 40); tableTwo.put(3L, "Fruits", 15); tableTwo.put(4L, "Vegetables", 35); // Stream方式合并Table Table<Long, String, Integer> sumTable = HashBasedTable.create(); // 合并两个Table的Cell流,分组累加值 Map<Map.Entry<Long, String>, Integer> mergedMap = Stream.concat( tableOne.cellSet().stream(), tableTwo.cellSet().stream()) .collect(Collectors.toMap( // 生成复合键:行键 + 列键 cell -> new AbstractMap.SimpleEntry<>(cell.getRowKey(), cell.getColumnKey()), Cell::getValue, // 重复键时执行累加操作 Integer::sum)); // 将Map转换为目标Table mergedMap.forEach((key, value) -> sumTable.put(key.getKey(), key.getValue(), value)); // 打印验证结果 sumTable.cellSet().forEach(cell -> System.out.printf("%s %s %d%n", cell.getRowKey(), cell.getColumnKey(), cell.getValue())); } }
关键步骤说明
Stream.concat:把两个Table的单元格流合并成一个统一的流Collectors.toMap:通过复合键分组,遇到重复键时调用Integer::sum完成值的累加- 最后遍历合并后的Map,将键值对映射回Table结构
传统迭代实现方式
如果更偏好直观的循环写法,这种方式也很容易理解:先复制第一个Table的所有数据到结果Table,再遍历第二个Table的每个单元格,检查是否存在重复键,存在则累加,不存在则直接插入。
import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; public class TableMergeTraditionalExample { public static void main(String[] args) { // 初始化示例数据 Table<Long, String, Integer> tableOne = HashBasedTable.create(); tableOne.put(1L, "Fruits", 20); tableOne.put(2L, "Fruits", 30); tableOne.put(2L, "Vegetables", 15); tableOne.put(3L, "Vegetables", 10); Table<Long, String, Integer> tableTwo = HashBasedTable.create(); tableTwo.put(2L, "Fruits", 10); tableTwo.put(2L, "Vegetables", 40); tableTwo.put(3L, "Fruits", 15); tableTwo.put(4L, "Vegetables", 35); // 传统方式合并Table Table<Long, String, Integer> sumTable = HashBasedTable.create(tableOne); // 先复制tableOne的所有数据 // 遍历tableTwo的每个单元格 for (Table.Cell<Long, String, Integer> cell : tableTwo.cellSet()) { Long rowKey = cell.getRowKey(); String columnKey = cell.getColumnKey(); Integer newValue = cell.getValue(); // 检查结果Table中是否已有该组合键 if (sumTable.contains(rowKey, columnKey)) { Integer existingValue = sumTable.get(rowKey, columnKey); sumTable.put(rowKey, columnKey, existingValue + newValue); } else { sumTable.put(rowKey, columnKey, newValue); } } // 打印验证结果 sumTable.cellSet().forEach(cell -> System.out.printf("%s %s %d%n", cell.getRowKey(), cell.getColumnKey(), cell.getValue())); } }
关键步骤说明
HashBasedTable.create(tableOne):快速复制第一个Table的所有数据到结果表,避免手动遍历插入- 遍历第二个Table时,用
contains(rowKey, columnKey)判断是否存在重复键,按需执行累加或插入操作
验证结果
两种方式运行后,都会输出符合你预期的结果:
1 Fruits 20 2 Fruits 40 2 Vegetables 55 3 Vegetables 10 3 Fruits 15 4 Vegetables 35
内容的提问来源于stack exchange,提问作者Sunflame
相关产品推荐
相关产品推荐

