英文:
How to flatten and sort a HashMap with ArrayList values in Java?
问题
所以,我有一个哈希映射,其中键为字符串,值为ArrayList。
static HashMap<String, ArrayList
然后我只是使用Scanner类请求输入:
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 100 2 200 3 300 1 200`,
我会得到`{1=[100, 200], 2=[200], 3=[300]}`
现在我需要这个哈希映射被“打开”,看起来像这样:`3 300 1 200 2 200 1 100`。
请注意,输出按**值**降序排序。
我还尝试过不同的方法,如SortedTreeMap或TreeBag,但似乎都不起作用。
英文:
So, I have a hashmap which has a String as key, and an Arraylist as Value.
static HashMap<String, ArrayList<Integer>> scores = new HashMap<>();
Then I just request Input with the Scanner Class:
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
String[] inputArr = input.split(" ");
And then I just add the score to the player if he exists, and if he doesn't it just creates a new entry
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);
}
}
So for example, if I Input 1 100 2 200 3 300 1 200
into the console,
I receive {1=[100, 200], 2=[200], 3=[300]}
Now what I need is this Hashmap to be "opened up" and look like this: 3 300 1 200 2 200 1 100
.
Note that the Output is sorted descending by value.
I also tried different methods, like a SortedTreeMap or a TreeBag, but none of them seem to work
答案1
得分: 2
你可以在地图的条目上执行flatMap
操作,将每个String
条目转换为List<Integer>
,形成多个String
到Integer
的条目流。然后,你可以使用你喜欢的比较器对条目进行排序。
var result = scores.entrySet().stream()
.flatMap(
entry -> entry.getValue().stream().map(v -> Map.entry(entry.getKey(), v))
)
.sorted(
Map.Entry.<String, Integer>comparingByValue().reversed()
// if you would like to also break ties on the values by comparing the keys
//.thenComparing(Map.Entry.comparingByKey())
)
.toList();
result
是一个List<Entry<String, Integer>>
。打印result
会得到:
[3=300, 1=200, 2=200, 1=100]
另外,请注意,将用户输入添加到地图的if
语句可以简化为以下使用computeIfAbsent
的形式:
scores.computeIfAbsent(UID, x -> new ArrayList<>()).add(score);
(注意:这是你的代码的翻译,不包括代码部分。)
英文:
You could do a flatMap
on the map's entries, transforming each entry of String
to List<Integer>
, into a stream of multiple entries of String
to Integer
. Then you can just sort the entries with a comparator you prefer.
var result = scores.entrySet().stream()
.flatMap(
entry -> entry.getValue().stream().map(v -> Map.entry(entry.getKey(), v))
)
.sorted(
Map.Entry.<String, Integer>comparingByValue().reversed()
// if you would like to also break ties on the values by comparing the keys
//.thenComparing(Map.Entry.comparingByKey())
)
.toList();
result
is a List<Entry<String, Integer>>
. Printing result
gives you
[3=300, 1=200, 2=200, 1=100]
Also note that your if statement for adding the user input into the map can be simplified to the following using computeIfAbsent
:
scores.computeIfAbsent(UID, x -> new ArrayList<>()).add(score);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论