Java Компаратор SortMap для заказа ключей di git после буквенных ключей - PullRequest
4 голосов
/ 04 апреля 2020

Мне нужна SortedMap, где ключи Charachter сортируются следующим образом: ('A' .. 'Z' .. '0' .. '9'), поэтому сначала введите символ, затем цифры, все в порядке возрастания. Это то, что я пробовал до сих пор, однако вывод показывает, что он не может вернуть нужную сортировку, потому что значения ключей di git все еще перед значениями буквенных ключей. Что я делаю неправильно? Есть ли еще лучший способ сделать это? Заранее спасибо!

public static void main(String[] args) {
    SortedMap<Character, String> sortedMap = new TreeMap<>(new Comparator<Character>() {
        @Override
        public int compare(Character o1, Character o2) {
            if (Character.isDigit(o1) && Character.isLetter(o2)){
                return o2.compareTo(o1);
            }
            else if(Character.isLetter(o1) && Character.isDigit(o2)){
                return o1.compareTo(o2);
            }
            else{
                return o1.compareTo(o2);
            }
        }
    });

    sortedMap.put('5', "five");
    sortedMap.put('8', "nine");
    sortedMap.put('A', "ALPHA");
    sortedMap.put('G', "GOLF");
    sortedMap.put('F', "FOXTROT");
    System.out.println(sortedMap.values());
}

Ответы [ 5 ]

2 голосов
/ 04 апреля 2020

Вы должны всегда возвращать -1, если o1 - это буква, а o2 - это ди git, потому что вы всегда хотите, чтобы буква go была первой. И вы всегда должны возвращать 1, если все наоборот.

Единственный случай, когда он должен возвращать o1.compareTo(o2), находится в конечном else, что означает, что o1 и o2 являются либо буквами, либо цифрами, и в этом случае компаратор должен просто следовать естественный порядок.

2 голосов
/ 04 апреля 2020

Вам необходимо вернуть результат «o1> o2», если o1 - это di git, а o2 - это буква, поэтому в этом случае верните 1. Аналогично, если o1 - это буква, а o2 - это ди git, вам нужно вернуть результат «o1

public int compare(Character o1, Character o2) {
   if (Character.isDigit(o1) && Character.isLetter(o2)){
      return 1;
   }
   else if(Character.isLetter(o1) && Character.isDigit(o2)){
      return -1;
   }
   else{
      return o1.compareTo(o2);
   }
}
1 голос
/ 04 апреля 2020

Если вы используете Java 8+, объявите вашу Карту как:

SortedMap<Character, String> sortedMap = 
            new TreeMap<>(Comparator.comparingInt(c -> (c + 197) % 255));

При желании вы можете извлечь "маги c числа" 197 и 255 в константы или извлечь аргумент из comparingInt(..) в константу.

Пояснение:
символы 0..9 соответствуют кодам ASCII 48..57
Коды ASCII для всех букв принадлежат диапазону 65..122
Код выше сдвигает коды немного, подвижные числа варьируются до 245..254, а буквы - до 7..64
Поскольку Comparator сравнивает сдвинутые коды, он помещает буквы перед цифрами

0 голосов
/ 04 апреля 2020

Я предпочитаю использовать конструкцию ternary (?:) вне объявления Map для построения Comparator. Я также добавил некоторые дополнительные значения, добавленные к вашему, чтобы добавить изменчивость.

        Comparator<Character> comp = (a, b) -> Character.isLetter(a)
                && Character.isDigit(b) ? -1 :
                Character.isLetter(b) && Character.isDigit(a) ? 1 :
                a.compareTo(b);

        SortedMap<Character, String> sortedMap = new TreeMap<>(comp);
        sortedMap.put('Q', "Quebec");
        sortedMap.put('B', "Beta");
        sortedMap.put('5', "five");
        sortedMap.put('9', "nine");
        sortedMap.put('A', "ALPHA");
        sortedMap.put('3', "three");
        sortedMap.put('G', "GOLF");
        sortedMap.put('F', "FOXTROT");
        sortedMap.entrySet().forEach(System.out::println);

Печать


A=ALPHA
B=BETA
F=FOXTROT
G=GOLF
Q=QUEBEC
3=three
5=five
9=nine
0 голосов
/ 04 апреля 2020

Если вы хотите, чтобы все буквы предшествовали всем цифрам, и вы получили одну ди git и одну букву, вам не следует сравнивать их вообще:

public int compare(Character o1, Character o2) {
    if (Character.isDigit(o1) && Character.isLetter(o2)) {
        // o1 < o2 regardless of what values o1 and o2 are
        // So return any negative integer
        return -100;
    }
    else if (Character.isLetter(o1) && Character.isDigit(o2)) {
        // o1 > o2 regardless of what values o1 and o2 are
        // So return any positive integer
        return 100;
    }
    // Both must be letters or both must be integers
    // fall back to normal comparison, as you have already done
    return o1.compareTo(o2);
}
...