0

我知道这个问题的答案已在许多变体中提供,但我无法为我的特定查询找到它。

我想要一个按值排序的地图,我需要在将数据放入其中之前创建它。我想出了下面的代码来创建它

private Map<String, Integer> mapUserScore = new ConcurrentSkipListMap<>(new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        int i1=mapUserScore.get(o2);
        int i2=mapUserScore.get(o1);
        if(mapUserScore.get(o2)!=null && mapUserScore.get(o1)!=null){
            int compare =  mapUserScore.get(o2)-(mapUserScore.get(o1));
            if(compare==0)compare=-1;
            return compare;
        }else
            return 0;
    }
});

所以基本上我希望地图中的条目按整数值降序排序,以便得分最高的人排在首位。但是,在插入第一个键值对时执行此操作,程序退出并出现以下异常

Exception in thread "Thread-0" java.lang.StackOverflowError
at java.util.concurrent.ConcurrentSkipListMap.comparable(ConcurrentSkipListMap.java:658)
at java.util.concurrent.ConcurrentSkipListMap.doGet(ConcurrentSkipListMap.java:821)
at java.util.concurrent.ConcurrentSkipListMap.get(ConcurrentSkipListMap.java:1626)

跟踪后,我发现int i1=mapUserScore.get(o2)行会导致此异常。谁能帮我理解这里stackoverflow的原因是什么?我在想,因为在任何项目存储在地图中之前,代码试图通过使用 get() 方法对其进行排序来获取它,因此它会进入一些递归调用并导致异常。

4

2 回答 2

1

如果我理解正确,您希望能够快速获得与名称相关联的分数(因此需要地图),并且您希望能够首先迭代具有最高分数的名称-分数对。

我只会使用 a HashMap<String, NameScore>(其中键是名称,值是名称-分数对)。这将为您提供 O(1) 查找。当您需要按分数排序的名称-分数对时,ArrayList<NameScore>values()地图中创建一个新的,对其进行排序并返回它。

于 2012-07-18T08:56:28.817 回答
0

get() 方法使用比较器来查找值。您不能在比较器中使用 get ,否则您将获得堆栈溢出。

一个简单的解决方法是将分数包含在键中并对其进行排序。

class NameScore implement Comparable<NameScore> {
     String name;
     int score;

}

顺便说一句:当比较器返回 0 时,这意味着它是重复的,它被丢弃了。除非您希望每个分数只有一个名称,否则您需要比较分数和名称。

于 2012-07-18T08:45:59.197 回答