【问题标题】:Java SortMap Comparator to have digit keys ordered after letter keysJava SortedMap Comparator 在字母键之后排序数字键
【发布时间】:2020-07-16 06:45:17
【问题描述】:

我需要一个 SortedMap,其中的字符键按以下方式排序:('A'..'Z'..'0'..'9'),所以首先是字符,然后是数字,所有这些都按升序排列。 这是我到目前为止所尝试的,但是,输出显示它无法返回我想要的排序,因为数字键的值仍然在字母键的值之前。 我究竟做错了什么?有没有更好的方法来做到这一点? 提前致谢!

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());
}

【问题讨论】:

    标签: java comparator digits letter sortedmap


    【解决方案1】:

    如果 o1 是数字而 o2 是字母,则需要返回结果“o1 > o2”,所以在这种情况下返回 1。同样,如果o1是字母,o2是数字,则需要返回结果“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);
       }
    }
    

    【讨论】:

      【解决方案2】:

      如果o1 是一个字母而o2 是一个数字,则您应该始终返回-1,因为您始终希望字母在前。如果相反,您应该始终返回 1。

      它应该返回o1.compareTo(o2) 的唯一情况是在最后的else 中,这意味着o1o2 都是字母或数字,在这种情况下,比较器应该简单地遵循自然顺序。

      【讨论】:

        【解决方案3】:

        假设您使用的是 Java 8+,请将您的 Map 声明为:

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

        或者,您可以将“幻数”197 和 255 提取到常量中,或者将comparingInt(..) 的参数提取到常量中。

        说明:
        字符 0..9 对应 ASCII 码 48..57
        所有字母的 ASCII 码都属于范围 65..122
        上面的代码稍微移动了代码,将数字范围移动到 245..254,将字母范围移动到 7..64
        由于 Comparator 比较移位的代码,它会将字母放在数字之前

        【讨论】:

        • 不错的解决方案。 +1。
        【解决方案4】:

        当您希望所有字母都在所有数字之前,并且您得到一个数字和一个字母时,您根本不应该比较它们:

        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);
        }
        

        【讨论】:

        • 是的,它有效,但这是一个坏习惯。始终返回 1、-1 或 0。
        【解决方案5】:

        我更喜欢在 Map 声明之外使用 ternary (?:) 构造来构建 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-26
          • 2018-07-27
          • 1970-01-01
          • 2014-04-13
          • 1970-01-01
          • 2019-01-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多