Guava Multimap/HashMap数值求和与按键值排序方案咨询
嘿,这个问题我刚好有经验,来给你拆解一下~
用Guava Multimap实现求和+排序的具体步骤
假设你已经用HashMultimap存储了你的数据(键+对应的多个int值),要实现按键对应数值总和降序排序,其实分两步走就行:先统计每个键的总和,再对总和排序。
1. 统计每个键的数值总和
首先遍历Multimap的所有键,计算每个键对应值的总和,把结果存到一个普通Map里:
import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.HashMap; import java.util.Map; public class MultimapSumSort { public static void main(String[] args) { // 初始化你的Multimap Multimap<String, Integer> multimap = HashMultimap.create(); multimap.put("A", 10); multimap.put("A", 20); multimap.put("B", 15); multimap.put("C", 30); multimap.put("B", 5); // 统计每个键的总和 Map<String, Integer> keyToSum = new HashMap<>(); for (String key : multimap.keySet()) { // 用Stream求和,简洁高效 int total = multimap.get(key).stream() .mapToInt(Integer::intValue) .sum(); keyToSum.put(key, total); } } }
2. 按总和降序排序
拿到总和Map后,我们可以把它的entry转成列表,然后自定义排序规则:
import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 接上面的代码 // 方式一:用List排序后转成有序Map List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(keyToSum.entrySet()); sortedEntries.sort((entry1, entry2) -> // 降序排序,注意是entry2.getValue() - entry1.getValue() Integer.compare(entry2.getValue(), entry1.getValue()) ); // 如果需要保留排序后的Map结构,可以用LinkedHashMap Map<String, Integer> sortedSumMap = new LinkedHashMap<>(); sortedEntries.forEach(entry -> sortedSumMap.put(entry.getKey(), entry.getValue())); // 方式二:用Java 8 Stream一步到位 List<Map.Entry<String, Integer>> sortedEntriesStream = keyToSum.entrySet() .stream() .sorted(Map.Entry.comparingByValue(java.util.Comparator.reverseOrder())) .collect(Collectors.toList());
如果遇到多个键总和相同的情况,你可以在排序规则里加次要条件(比如按键的字典序排序),确保排序稳定:
sortedEntries.sort((entry1, entry2) -> { int valueCompare = Integer.compare(entry2.getValue(), entry1.getValue()); if (valueCompare != 0) { return valueCompare; } // 总和相同时,按键升序排列 return entry1.getKey().compareTo(entry2.getKey()); });
更高效的存储方案思考
其实如果你的核心需求是统计每个键的数值总和,那一开始用Multimap并不是最高效的选择——因为Multimap会存储每个键对应的所有单个值,后续还要额外求和,既占内存又多了一步计算。
更高效的方案是直接用普通的Map<K, Integer>实时累加:
Map<String, Integer> sumMap = new HashMap<>(); // 当你要添加一条数据(key, value)时,直接累加 sumMap.put("A", sumMap.getOrDefault("A", 0) + 10); sumMap.put("A", sumMap.getOrDefault("A", 0) + 20); // 这样sumMap里"A"的值直接就是30,不用后续再求和
这种方案的优势:
- 内存更省:不需要存储重复键的多个值,直接维护总和
- 效率更高:实时累加,避免了后续遍历求和的开销
- 代码更简洁:省去了从Multimap转Map求和的步骤
当然,如果你的业务场景还需要保留每个键对应的所有单个值(比如除了总和,还要查看每个具体的数值),那Multimap是合适的选择——这时候就只能先存再求和排序了。
内容的提问来源于stack exchange,提问作者Choobak Music
相关产品推荐
相关产品推荐

