[英]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.