本问题已经有最佳答案,请猛点这里访问。
我对字符串的默认比较器(在SortedSet中)有问题。 问题是默认比较器没有排序包含数字的良好字符串,即:
在集合我有:
room1, room2, room100
自然排序应该如上所述,但在集合中我有:
room1, room100, room2
我知道它为什么但我不知道如何改变它。
您需要创建自定义比较器
我知道,但我不知道如何比较它。 知道我正在尝试这个:> private int compareNumbers(String o1,String o2){Pattern numberPattern = Pattern.compile(PATTERN); Matcher matcher1 = numberPattern.matcher(o1); Matcher matcher2 = numberPattern.matcher(o2); int i1 = Integer.parseInt(matcher1.group()); int i2 = Integer.parseInt(matcher2.group()); System.out.println(i1 +""+ i2); 返回i1 - i2;}
你需要做出假设,例如,所有字符串都以的格式? 或者决定你的格式究竟是什么,只有这样你才能编写你的比较器
尝试使用此比较器,删除所有非数字字符,然后将剩余字符作为数字进行比较:
Collections.sort(strings, new Comparator() {
public int compare(String o1, String o2) {
return extractInt(o1) - extractInt(o2);
}
int extractInt(String s) {
String num = s.replaceAll("\\D","");
// return 0 if no digits found
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
这是一个测试:
public static void main(String[] args) throws IOException {
List strings = Arrays.asList("room1","foo","room2","room100","room10");
Collections.sort(strings, new Comparator() {
public int compare(String o1, String o2) {
return extractInt(o1) - extractInt(o2);
}
int extractInt(String s) {
String num = s.replaceAll("\\D","");
// return 0 if no digits found
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
System.out.println(strings);
}
输出:
[foo, room1, room2, room10, room100]
为什么我使用List strings = Arrays.asList("a","aaa")运行算法; 结果与List strings = Arrays.asList("aaa","a")不同;? 我相信结果应该是一样的。 请告诉我,如果我出错了...
@Bohemian我如何排序这一行但按顺序排列:[room1,room2,room10,room100,foo]首先 - 反向字母表第二 - 按顺序排列?
这篇文章很老了,但是:@PonomarenkoOleh返回num.isEmpty()? 1:Integer.parseInt(num); 尝试1而不是0。
使用了@bohemian的回答。刚刚改进了一下。这对我很有用..
Collections.sort(asdf, new Comparator() {
public int compare(String o1, String o2) {
String o1StringPart = o1.replaceAll("\\d","");
String o2StringPart = o2.replaceAll("\\d","");
if(o1StringPart.equalsIgnoreCase(o2StringPart))
{
return extractInt(o1) - extractInt(o2);
}
return o1.compareTo(o2);
}
int extractInt(String s) {
String num = s.replaceAll("\\D","");
// return 0 if no digits found
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
试试这个。我假设你的字符串开头总是有"空间"。
List list = Arrays.asList("room1","room100","room2");
Collections.sort(list, new Comparator()
{
@Override
public int compare(String o1, String o2)
{
return new Integer(o1.replaceAll("room",""))
.compareTo(new Integer(o2.replaceAll("room","")));
}
});
这是我的Comparator实现这样的一种:
(字符串可以从任何字符开始)
public class StringNumberComparator implements Comparator{
@Override
public int compare(String o1, String o2) {
int i1 = this.getRearInt(o1);
int i2 = getLeadingInt(o2);
String s1 = getTrailingString(o1);
String s2 = getTrailingString(o2);
if(i1==i2)
return s1.compareTo(s2);
if(i1>i2)
return 1;
else if(i1
return -1;
return 0;
}
private int getRearInt(String s) {
s=s.trim();
int i=Integer.MAX_VALUE;
try {
i = Integer.parseInt(s.split("[^0-9]+")[1]);
} catch(ArrayIndexOutOfBoundsException e) {
} catch(NumberFormatException f) {
return i;
}
return i;
}
private String getTrailingString(String s) {
return s.replaceFirst("[0-9]","");
}
}
一个懒惰的替代方案是使String比较器工作而不做任何额外的事情(定义你自己的比较器)。您可以通过使用零填充String中的数字,如下所示:room0001, room0002, room0100然后默认的字符串比较器将起作用。但是,您需要知道最大数值,以便相应地调整填充。
您可以实现比较器并将其传递给set构造函数。
请参见http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html。
如果您的所有字符串都是房间[数字]的形式,您可以剥离"房间"解析数字并进行比较。
或者 - 您可以在设置中存储整数并使用"room"前缀打印它们。
但我不知道如何比较它。 一些正则表达式?
字符串总是以房间[数字]的形式出现吗?