0

いくつかの値を格納した TreeMap があります。マップは値を使用して、最高から最低の順に並べ替えられます。ここで、TreeMap の内容をさまざまなインデックスと共に出力したいと思います。

マップに次のペアがある場合:

("Andrew", 10),
("John", 5),
("Don",9),
("Rolex", 30),
("Jack", 10),
("Dan",9)

印刷したい:

Rolex, 30 , 1
Jack, 10, 2
Andrew, 10, 2
Dan, 9, 4
Don, 9, 4
John, 5, 6.

これは私が試してきたものですが、うまく機能していないようです:

/**
 *
 * @author Andrew
 */

import java.util.*;

public class SortArray {

    static <K,V extends Comparable<? super V>> SortedSet<Map.Entry<K,V>>entriesSortedByValues(Map<K,V> map) {
        SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
                new Comparator<Map.Entry<K,V>>() {
                    @Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
                         int res = e1.getValue().compareTo(e2.getValue());
                        return res!= 0 ? res : 1;
                        //return e1.getValue().compareTo(e2.getValue());
                    }
                });
        sortedEntries.addAll(map.entrySet());
        return sortedEntries;
    }



    public void test(){
        Map mm = new TreeMap();
        mm.put("Andrew", 11);
        mm.put("Mbata", 21);
        mm.put("Chinedu", 14);
        mm.put("Bol", 14);
        mm.put("Don", 51);
        mm.put("Rolex", 16);
        mm.put("Son", 41);
        SortedSet newMap =  entriesSortedByValues(mm);
        Iterator iter = newMap.iterator();
        int x = newMap.size();
        List names = new ArrayList();
        List scores = new ArrayList();
        while(iter.hasNext()){
            String details = iter.next().toString();
            StringTokenizer st = new StringTokenizer(details, "=");
            String name = st.nextToken();
            names.add(name);
            String score = st.nextToken();
            scores.add(score);
            //System.out.println(name + " Score:" +score + " Position:" + x);
            x--;
        }
        Collections.reverse(names);
        Collections.reverse(scores);
        int pos = 1;

        for(int i = 0; i<names.size();){
            try{
                int y = i+1;
                if(scores.get(i).equals(scores.get(y))){
                    System.out.print("Name: "+ names.get(i)+"\t");
                    System.out.print("Score: "+ scores.get(i)+"\t");
                    System.out.println("Position: "+ String.valueOf(pos));
                    //pos++;
                    i++;
                    continue;
                } else{
                    System.out.print("Name: "+ names.get(i)+"\t");
                    System.out.print("Score: "+ scores.get(i)+"\t");
                    System.out.println("Position: "+ String.valueOf(pos++));
                }
                i++;

            } catch(IndexOutOfBoundsException e) {}
        }
    }

    public SortArray(){
        test();
    }

    public static void main(String [] args){
        new SortArray();
    }
}
4

3 に答える 3

0

toString() を呼び出してから、結果を分割するなど、イテレータで多くの作業を行います。そしてあなたの Comparator も余分な仕事です。両側で Map を使用します。keys() と values() をより直接的に使用して、Java にソートを任せることができます。上記のコードのほとんどは次のように置き換えることができます: (わかりやすくするために、名前を「mm」から「originalMap」に変更しました)

Map<Integer, String> inverseMap = new TreeMap<Integer, String>();
for (Map.Entry<String, Integer> entry : originalMap.entrySet()) {
  inverseMap.put(entry.getValue(), entry.getKey());
}

ここで、inverseMap を反復処理して結果を出力します。カウントが originalMap に 2 回存在する場合、1 つだけが出力されることに注意してください。しかし、どれが印刷されるかは、読者の演習として残しておきます:-)。あなたはそれについてもっと具体的にしたいかもしれません。

追加された編集:重複したスコアを印刷したい場合、これはあなたが望むものではありません。私が読んだ元の投稿は、それらが同じ場合はスキップすると言っていましたが、編集後にそれが表示されないため、これがOPが望んでいるものかどうかはわかりません.

于 2013-06-25T00:36:05.523 に答える
0

あなたSortedSetのやり方は間違っています。両方の値を同じキーで検索する必要がある場合、少し乱雑になることがわかりますComparator。この乱雑な (そして正しくない) return res != 0 ? res : 1(常に を返すのではなく、1実際にはそうすべきです)。e1.getKey().compareTo(e2.getKey())1

Listこれを行うためのより良い方法は、別の を作成するのではなく、 でキーを自分でソートすることSortedSetです。これにより、並べ替え値の重複について心配する必要がなくなります。

Comparator必要に応じて、後で他のコードで再利用しやすくするために、内容を少し抽象化することもできます。

import java.util.*;

public class PrintSomething {
    public static <T extends Comparable<T>> Comparator<T> reverseComparator(final Comparator<T> oldComparator) {
        return new Comparator<T>() {
            @Override
            public int compare(T o1, T o2) {
                return oldComparator.compare(o2, o1);
            }
        };
    }

    public static <K,V extends Comparable<V>> Comparator<K> keyedComparator(final Map<K,V> lookup) {
        return new Comparator<K>() {
            @Override
            public int compare(K o1, K o2) {
                return lookup.get(o1).compareTo(lookup.get(o2));
            }
        };
    }

    public static void main(String[] args) {
        Map<String, Integer> mm = new HashMap<>();
        mm.put("Andrew", 10);
        mm.put("John", 5);
        mm.put("Don", 9);
        mm.put("Rolex", 30);
        mm.put("Jack", 10);
        mm.put("Dan", 9);

        Comparator<String> comparator = reverseComparator(keyedComparator(mm));
        List<String> keys = Arrays.asList(mm.keySet().toArray(new String[mm.size()]));
        //Collections.sort(keys); // optional, if you want the names to be alphabetical
        Collections.sort(keys, comparator);

        int rank = 1, count = 0;
        Integer lastVal = null;
        for (String key : keys) {
            if (mm.get(key).equals(lastVal)) {
                count++;
            } else {
                rank += count;
                count = 1;
            }
            lastVal = mm.get(key);
            System.out.println(key + ", " + mm.get(key) + ", " + rank);
        }
    }
}

一般SortedSetに、データ自体をソートしておく必要がある場合は、次のような方が理にかなっています。一度ソートされた方法で何かを処理する必要がある場合、それらは通常、価値があるよりも面倒です。(また、値ではなくTreeMap? sを使用してキーを並べ替える理由があるので、この場合、その並べ替えを利用していません。その場合、 a を使用する方が一般的です。)TreeMapHashMap

于 2013-06-25T00:34:28.860 に答える