繁体   English   中英

在java中用字符串元素排序集合

[英]sorting collections with string elements in java

我有一个集合......我编写代码使用我自己的比较器对比值进行排序我的比较器代码是

private static class MatchComparator implements Comparator<xmlparse> {
    @Override
    public int compare(xmlparse object1, xmlparse object2) {
        String match1 = object1.getMatchId();
        String match2 = object2.getMatchId();
        return match1.compareTo(match2);
    }
}

我将调用Collections.sort(list,new MatchComparator());

一切都很好,但我的问题是排序列表是错误的,当我打印它...

输入列表

Match19
Match7
Match12
Match46
Match32

排序列表的输出

Match12
Match19
Match32
Match46
Match7

我的预期输出是

Match7
Match12
Match19
Match32
Match46

要获得所需的订单,您可以将1位数字加前缀为零(例如Match07),或者您必须将字符串拆分为前缀和数字部分,并将排序实现为数字比较

问题是String.compareTo(..)比较单词char by char。

如果所有字符串都以Match开头,那么您可以通过以下方式轻松解决

public int compare(xmlparse object1, xmlparse object2) {
    String match1 = object1.getMatchId();
    String match2 = object2.getMatchId();
    return Integer.parseInt(match1.replace("Match"))
         - Integer.parseInt(match2.replace("Match"));
}

如果他们没有使用Match开始,那么你可以使用正则表达式:

Integer.parseInt(object1.replaceAll("[a-zA-Z]+", ""));

要么

Integer.parseInt(object1.replaceAll("[\p{Alpha}\p{Punch}]+", ""));

最后一点 - 用大写命名你的类,camelCase - 即XmlParse而不是xmlparse - 这就是约定所规定的。

比较是词典而不是数字,这是你的问题。 在lexicoraphic排序中,10在9之前。

有关开源实现解决方案,请参阅此问题 您还可以实现自己的字符串比较,这不应该那么难。

实现一个函数并将其用于比较:
代替

return match1.compareTo(match2);

采用

return compareNatural(match1,match2);

这是一个对字符串进行自然比较的函数:

private static int compareNatural(String s, String t, boolean caseSensitive) {
    int sIndex = 0;
    int tIndex = 0;

    int sLength = s.length();
    int tLength = t.length();

    while (true) {
        // both character indices are after a subword (or at zero)

        // Check if one string is at end
        if (sIndex == sLength && tIndex == tLength) {
            return 0;
        }
        if (sIndex == sLength) {
            return -1;
        }
        if (tIndex == tLength) {
            return 1;
        }

        // Compare sub word
        char sChar = s.charAt(sIndex);
        char tChar = t.charAt(tIndex);

        boolean sCharIsDigit = Character.isDigit(sChar);
        boolean tCharIsDigit = Character.isDigit(tChar);

        if (sCharIsDigit && tCharIsDigit) {
            // Compare numbers

            // skip leading 0s
            int sLeadingZeroCount = 0;
            while (sChar == '0') {
                ++sLeadingZeroCount;
                ++sIndex;
                if (sIndex == sLength) {
                    break;
                }
                sChar = s.charAt(sIndex);
            }
            int tLeadingZeroCount = 0;
            while (tChar == '0') {
                ++tLeadingZeroCount;
                ++tIndex;
                if (tIndex == tLength) {
                    break;
                }
                tChar = t.charAt(tIndex);
            }
            boolean sAllZero = sIndex == sLength || !Character.isDigit(sChar);
            boolean tAllZero = tIndex == tLength || !Character.isDigit(tChar);
            if (sAllZero && tAllZero) {
                continue;
            }
            if (sAllZero && !tAllZero) {
                return -1;
            }
            if (tAllZero) {
                return 1;
            }

            int diff = 0;
            do {
                if (diff == 0) {
                    diff = sChar - tChar;
                }
                ++sIndex;
                ++tIndex;
                if (sIndex == sLength && tIndex == tLength) {
                    return diff != 0 ? diff : sLeadingZeroCount - tLeadingZeroCount;
                }
                if (sIndex == sLength) {
                    if (diff == 0) {
                        return -1;
                    }
                    return Character.isDigit(t.charAt(tIndex)) ? -1 : diff;
                }
                if (tIndex == tLength) {
                    if (diff == 0) {
                        return 1;
                    }
                    return Character.isDigit(s.charAt(sIndex)) ? 1 : diff;
                }
                sChar = s.charAt(sIndex);
                tChar = t.charAt(tIndex);
                sCharIsDigit = Character.isDigit(sChar);
                tCharIsDigit = Character.isDigit(tChar);
                if (!sCharIsDigit && !tCharIsDigit) {
                    // both number sub words have the same length
                    if (diff != 0) {
                        return diff;
                    }
                    break;
                }
                if (!sCharIsDigit) {
                    return -1;
                }
                if (!tCharIsDigit) {
                    return 1;
                }
            } while (true);
        } else {
            // Compare words
            // No collator specified. All characters should be ascii only. Compare character-by-character.
            do {
                if (sChar != tChar) {
                    if (caseSensitive) {
                        return sChar - tChar;
                    }
                    sChar = Character.toUpperCase(sChar);
                    tChar = Character.toUpperCase(tChar);
                    if (sChar != tChar) {
                        sChar = Character.toLowerCase(sChar);
                        tChar = Character.toLowerCase(tChar);
                        if (sChar != tChar) {
                            return sChar - tChar;
                        }
                    }
                }
                ++sIndex;
                ++tIndex;
                if (sIndex == sLength && tIndex == tLength) {
                    return 0;
                }
                if (sIndex == sLength) {
                    return -1;
                }
                if (tIndex == tLength) {
                    return 1;
                }
                sChar = s.charAt(sIndex);
                tChar = t.charAt(tIndex);
                sCharIsDigit = Character.isDigit(sChar);
                tCharIsDigit = Character.isDigit(tChar);
            } while (!sCharIsDigit && !tCharIsDigit);
        }
    }
}

一个更好的是在这里

看来你不希望String.compareTo()真正是什么。 它执行所谓的词典编纂,但您尝试按编号进行比较。 您需要修改比较器的代码。

  @Override
        public int compare(xmlparse object1, xmlparse object2) {
            String match1 = object1.getMatchId();
            String match2 = object2.getMatchId();

            Long n1 = getNumber(match1);
            Long n2 = getNumber(match2);

            return n1.compareTo(n2);             
        }

其中getNumber()从字符串“matchXX”中提取最后一个nuber

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM