
本文讲解如何正确对 hashmap 按 integer 值升序排序并提取对应 character 键,解决原代码中因错误遍历与重复赋值导致所有数组元素被同一字符覆盖的问题。推荐使用 stream api 配合 linkedhashmap 保持插入顺序。
本文讲解如何正确对 hashmap 按 integer 值升序排序并提取对应 character 键,解决原代码中因错误遍历与重复赋值导致所有数组元素被同一字符覆盖的问题。推荐使用 stream api 配合 linkedhashmap 保持插入顺序。
原始代码存在多个根本性逻辑缺陷:
- 迭代中修改集合后继续遍历未重置状态:itr.remove() 删除当前 entry 后,while(itr.hasNext()) 仍会继续执行下一轮,但此时 min 和 k 已被固定为首次找到的最小非零值(如 'A'→1),后续循环不再更新;
- 内层 for 循环位置错误:newCharArray2[i] = k; 和 letterCount[i] = min; 被放在 for (int i = 0; i < newCharArray2.length; i++) 内部,导致每个迭代轮次都将整个数组填满同一个字符和数值(如 [A, A, A, A, A]),而非逐个填充不同字符;
- itr.remove() 仅移除当前 entry,但未跳过已处理项的重复比较,且 min 初始化缺失(应设为 Integer.MAX_VALUE),导致逻辑不可控;
- HashMap 本身无序,直接 entrySet().iterator() 无法保证按值升序访问。
✅ 正确解法:使用 Java 8+ Stream API 实现稳定、简洁、可读性强的按值排序:
// 按 value 升序排序,保留键值对顺序(使用 LinkedHashMap)
LinkedHashMap<Character, Integer> sortedMap = myHashMap.entrySet().stream()
.filter(entry -> entry.getValue() > 0) // 排除 0 值(符合题意“只关注 1+”)
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1, // 冲突时保留前者(实际不会冲突)
LinkedHashMap::new
));
// 提取排序后的字符数组与数值数组
Character[] charArray = sortedMap.keySet().toArray(new Character[0]);
Integer[] countArray = sortedMap.values().toArray(new Integer[0]);
System.out.println("Sorted chars: " + Arrays.toString(charArray));
System.out.println("Corresponding counts: " + Arrays.toString(countArray));输出示例(基于输入 letterCount = [1,2,0,2,0,0,0,2,0,0,1]):
Sorted chars: [A, K, B, D, H] Corresponding counts: [1, 1, 2, 2, 2]
? 关键注意事项:
立即学习“Java免费学习笔记(深入)”;
- filter(entry -> entry.getValue() > 0) 确保只处理有效计数,比在循环内用 != 0 判断更清晰安全;
- LinkedHashMap::new 是关键——它保证 collect() 结果按流处理顺序(即排序后顺序)存储,避免 HashMap 的无序性;
- 若需纯 char[] 和 int[],可用 sortedMap.keySet().stream().map(Character::charValue).toArray(char[]::new) 等方式转换;
- 切勿在增强 for 或普通 Iterator 遍历中混用 remove() 并同时修改共享变量(如 k, min)来模拟排序逻辑——这极易引发竞态与覆盖,应交由声明式 API 处理。
此方案时间复杂度为 O(n log n),语义明确,一次完成过滤、排序、重组,彻底规避手动迭代的易错性。


















