在将任何数据放入其中之前,创建按值排序的Map

时间:2012-07-18 08:38:04

标签: java

我知道这个问题的答案已经提供了很多变种,但我找不到我的具体查询。

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

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()方法对其进行排序来获取它,因此它会进入一些递归调用并导致异常。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您希望能够快速获得与名称相关联的分数(因此需要地图),并且您希望能够以最高的顺序遍历tyhe名称 - 分数对先得分。

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

答案 1 :(得分:0)

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

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

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

}

BTW:当比较器返回0时,这表示它是重复的,被丢弃。除非您每个分数只需要一个名称,否则您需要比较分数和名称。