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を返す場合、これは重複していることを意味し、ドロップされます。スコアごとに1つの名前だけが必要な場合を除いて、スコアと名前を比較する必要があります。

于 2012-07-18T08:45:59.197 に答える