如何在Java中扁平化并按值降序排序含ArrayList值的HashMap
解决方案
要实现将HashMap扁平化并按分数降序输出的需求,核心是先把每个用户的每一条分数拆分为独立的<UID, 分数>条目,再对这些条目按分数降序排序,最后拼接成目标字符串。具体实现如下:
完整代码示例
import java.util.*; import java.util.AbstractMap.SimpleEntry; public class ScoreProcessor { static HashMap<String, ArrayList<Integer>> scores = new HashMap<>(); public static void main(String[] args) { // 输入处理部分(保留你原有的代码) Scanner sc = new Scanner(System.in); String input = sc.nextLine(); String[] inputArr = input.split(" "); for (int i = 0; i < inputArr.length; i += 2) { String UID = inputArr[i]; int score = Integer.parseInt(inputArr[i + 1]); if (!scores.containsKey(UID)) { ArrayList<Integer> list = new ArrayList<>(); list.add(score); scores.put(UID, list); } else { scores.get(UID).add(score); } } // 扁平化并排序的核心逻辑 // 1. 提取所有<UID, 单个分数>条目 List<SimpleEntry<String, Integer>> flatScoreEntries = new ArrayList<>(); for (Map.Entry<String, ArrayList<Integer>> userEntry : scores.entrySet()) { String uid = userEntry.getKey(); for (int score : userEntry.getValue()) { flatScoreEntries.add(new SimpleEntry<>(uid, score)); } } // 2. 按分数降序排序 flatScoreEntries.sort((entry1, entry2) -> Integer.compare(entry2.getValue(), entry1.getValue())); // 3. 拼接输出字符串 StringBuilder result = new StringBuilder(); for (SimpleEntry<String, Integer> entry : flatScoreEntries) { result.append(entry.getKey()).append(" ").append(entry.getValue()).append(" "); } // 移除末尾多余的空格 if (result.length() > 0) { result.deleteCharAt(result.length() - 1); } // 输出结果 System.out.println(result.toString()); } }
关键逻辑说明
- 扁平化处理:遍历原HashMap的每个用户条目,将用户的每一条分数都拆分为独立的
SimpleEntry<String, Integer>对象,存入列表中。这样原本的多值结构就被转换成了单条目的列表,方便后续排序。 - 排序规则:使用Lambda表达式自定义比较器,让列表按分数的降序排列(
entry2.getValue()和entry1.getValue()交换位置实现降序)。如果需要对同分数的条目额外排序(比如按UID升序),可以在比较器中补充逻辑。 - 结果拼接:通过
StringBuilder高效拼接排序后的条目,最后移除末尾多余的空格,得到符合要求的输出格式。
为什么之前的方法无效?
SortedTreeMap是按**键(UID)**排序的,无法满足按值(每个单独分数)排序的需求,而且它只能为每个键保留一个值,不适合你的多分数场景。TreeBag主要用于统计元素的出现频率,无法处理<UID, 分数>这种键值对的排序需求。
内容的提问来源于stack exchange,提问作者Glandorf
相关产品推荐
相关产品推荐

