Как отсортировать TreeMap ‹String, Integer›?

У меня есть карта: TreeMap<String, Integer> m = new TreeMap<>();, где у меня есть целый алфавит и значения, которая показывает, сколько раз каждая буква была найдена в моем тексте.

Я хочу отсортировать эту карту в порядке убывания количества; то есть наиболее часто встречающаяся буква находится в первой строке, а последняя строка вывода указывает наименее часто используемую букву. Если две буквы имеют одинаковую частоту, то первой должна появиться буква, которая стоит первой в алфавите. Как это сделать?

Я пробовал с компаратором:

public int compare(String a, String b) {
        if (base.get(a) >= base.get(b) && a.compareToIgnoreCase(b) < 0) {
            return -1;
        } else {
            return 1;
        }
    }

но все же это не то, вывод:

D 3
E 3
A 2
S 5

Ребят ... Обнаружил раньше, совсем не помогло. Хороший выход должен быть:

S 5
D 3
E 3
A 2

person Katie    schedule 01.02.2013    source источник
comment
точный дубликат http://stackoverflow.com/questions/3074154/sorting-a-hashmap-based-on-value-then-key   -  person JohnJohnGa    schedule 01.02.2013
comment
еще один дубликат stackoverflow.com/questions/1448369/   -  person mellamokb    schedule 01.02.2013
comment
@JohnJohnGa: нет. У меня вопрос немного другой. Смотрите мое редактирование   -  person Katie    schedule 01.02.2013


Ответы (2)


Ваш компаратор выглядит неправильно - он должен работать лучше:

public int compare(String a, String b) {
    if (base.get(a) > base.get(b)) {
        return -1;
    } else if (base.get(a) < base.get(b)) {
        return 1;
    } else {
        int stringCompare = a.compareToIgnoreCase(b);
        return stringCompare == 0 ? 1 : stringCompare; // returning 0 would merge keys
    }
}
person assylias    schedule 01.02.2013
comment
@Katie Извините, это было в порядке возрастания - исправлено. - person assylias; 01.02.2013

Поскольку естественная сортировка не имеет ничего общего с вашим желанием сортировки:

List<Map.Entry<String, Integer>> entries = new ArrayList<>(m.entrieSet());

Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
    @Override
    public int compare(Map.Entry<String, Integer >a, Map.Entry<String, Integer>b) {
        if (a.getValue() < b.getValue()) { // Descending values
            return 1;
        } else if (a.getValue() > b.getValue()) {
            return -1;
        }
        return -a.getKey().compareTo(b.getKey()); // Descending keys
    }    
});
person Joop Eggen    schedule 01.02.2013
comment
+1. Поразительно плохая идея - пытаться написать компаратор по значению, как это делает OP, и обрекает ваш код на запутанные, неожиданные и невозможные для отладки беспорядки. - person Louis Wasserman; 01.02.2013