遍历HashMap获取字符-整数有序列表时仅得重复元素的问题
HashMap遍历取最小元素时重复输出单一元素的问题
我在Java中遍历HashMap,想按整数从小到大的顺序获取对应的字符列表,但结果只得到一个元素重复出现。我的思路是每次找到当前最小的非0值键值对后,用itr.remove()把它从Map中移除,这样下次迭代就能找下一个最小的。
问题代码
Iterator<Map.Entry<Character, Integer>> itr = myHashMap.entrySet().iterator(); while(itr.hasNext()) { Map.Entry<Character, Integer> entry = itr.next(); for (int i = 0; i < newCharArray2.length; i++) { if (entry.getValue() < min && entry.getValue() != 0) { min = entry.getValue(); k = entry.getKey(); itr.remove(); } newCharArray2[i] = k; letterCount[i] = min; } } System.out.println("New newCharArray letters: " + Arrays.toString(newCharArray2)); System.out.println("New letterCount numbers: " + Arrays.toString(letterCount));
相关数据
- 字母计数数组(对应A-K):
[1, 2, 0, 2, 0, 0, 0, 2, 0, 0, 1] - HashMap初始化代码:
myHashMap.put('A', letterCount[0]); myHashMap.put('B', letterCount[1]); myHashMap.put('C', letterCount[2]); myHashMap.put('D', letterCount[3]); myHashMap.put('E', letterCount[4]); myHashMap.put('F', letterCount[5]); myHashMap.put('G', letterCount[6]); myHashMap.put('H', letterCount[7]); myHashMap.put('I', letterCount[8]); myHashMap.put('J', letterCount[9]); myHashMap.put('K', letterCount[10]);
实际输出
New newCharArray letters: [A, A, A, A, A] New letterCount numbers: [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
问题分析
你的代码逻辑存在核心错误:
- 嵌套循环顺序错误:外层迭代器每次仅取一个entry,但内层直接遍历整个
newCharArray2数组,把当前的k和min填充到所有位置。这导致第一次拿到的元素(A,值1)直接覆盖整个数组,后续迭代的修改完全无法生效。 min的逻辑矛盾:如果min默认是int初始值0,entry.getValue() < min对所有非0值都不成立;即便你提前把min设为大数,内层循环的覆盖问题依然会让数组全是第一个元素。itr.remove()时机错误:在数组遍历循环中就移除当前entry,后续迭代的entry根本没机会修改已经被填满的数组。
正确解决方案
没必要用迭代器边遍历边删除,更高效的方式是先过滤、排序,再填充数组:
方案1:Stream API实现(Java 8+)
import java.util.stream.Collectors; import java.util.List; // 过滤非0元素并按值从小到大排序 List<Map.Entry<Character, Integer>> sortedEntries = myHashMap.entrySet().stream() .filter(entry -> entry.getValue() != 0) .sorted(Map.Entry.comparingByValue()) .collect(Collectors.toList()); // 填充目标数组(避免数组越界) for (int i = 0; i < sortedEntries.size() && i < newCharArray2.length; i++) { Map.Entry<Character, Integer> entry = sortedEntries.get(i); newCharArray2[i] = entry.getKey(); letterCount[i] = entry.getValue(); } // 输出结果 System.out.println("New newCharArray letters: " + Arrays.toString(newCharArray2)); System.out.println("New letterCount numbers: " + Arrays.toString(letterCount));
方案2:传统方式(兼容低版本Java)
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; // 过滤出非0的键值对 List<Map.Entry<Character, Integer>> entryList = new ArrayList<>(); for (Map.Entry<Character, Integer> entry : myHashMap.entrySet()) { if (entry.getValue() != 0) { entryList.add(entry); } } // 按值从小到大排序 Collections.sort(entryList, new Comparator<Map.Entry<Character, Integer>>() { @Override public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) { return o1.getValue().compareTo(o2.getValue()); } }); // 填充数组 for (int i = 0; i < entryList.size() && i < newCharArray2.length; i++) { Map.Entry<Character, Integer> entry = entryList.get(i); newCharArray2[i] = entry.getKey(); letterCount[i] = entry.getValue(); }
说明
- 先过滤值为0的元素,避免无效处理;
- 通过排序直接得到按值从小到大的有序列表,无需手动查找最小值;
- 遍历排序后的列表依次填充数组,即可得到有序的字符和对应数值。
内容的提问来源于stack exchange,提问作者Alexandra
相关产品推荐
相关产品推荐

