Beim Sortieren der Schlüssel muss der Comparator jeden Wert für jeden Vergleich nachschlagen. Eine skalierbarere Lösung würde das entrySet direkt verwenden, da dann der Wert für jeden Vergleich sofort verfügbar wäre (obwohl ich dies nicht mit Zahlen untermauert habe).
Hier ist eine generische Version einer solchen Sache:
public static <K, V extends Comparable<? super V>> List<K> getKeysSortedByValue(Map<K, V> map) {
final int size = map.size();
final List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size);
list.addAll(map.entrySet());
final ValueComparator<V> cmp = new ValueComparator<V>();
Collections.sort(list, cmp);
final List<K> keys = new ArrayList<K>(size);
for (int i = 0; i < size; i++) {
keys.set(i, list.get(i).getKey());
}
return keys;
}
private static final class ValueComparator<V extends Comparable<? super V>>
implements Comparator<Map.Entry<?, V>> {
public int compare(Map.Entry<?, V> o1, Map.Entry<?, V> o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
Es gibt Möglichkeiten, die Speicherrotation für die obige Lösung zu verringern. Die erste erstellte ArrayList könnte zum Beispiel als Rückgabewert wiederverwendet werden; dies würde die Unterdrückung einiger generischer Warnungen erfordern, aber es könnte sich für wiederverwendbaren Bibliothekscode lohnen. Außerdem muss der Comparator nicht bei jedem Aufruf neu zugewiesen werden.
Hier ist eine effizientere, wenn auch weniger ansprechende Version:
public static <K, V extends Comparable<? super V>> List<K> getKeysSortedByValue2(Map<K, V> map) {
final int size = map.size();
final List reusedList = new ArrayList(size);
final List<Map.Entry<K, V>> meView = reusedList;
meView.addAll(map.entrySet());
Collections.sort(meView, SINGLE);
final List<K> keyView = reusedList;
for (int i = 0; i < size; i++) {
keyView.set(i, meView.get(i).getKey());
}
return keyView;
}
private static final Comparator SINGLE = new ValueComparator();
Wenn Sie schließlich ständig auf die sortierten Informationen zugreifen müssen (anstatt sie nur ab und zu zu sortieren), können Sie eine zusätzliche Multikarte verwenden. Lassen Sie es mich wissen, wenn Sie mehr Details benötigen...