假设我有一个字符串列表,例如'ABC123','XXY111','EFG001'等。
我需要用两种方式对这些字符串进行排序,
1)首先,它将按数字排序。
2)然后将按字母排序。
我尝试使用比较器对字符串进行排序。
首先,我分割字符串并在开头加上数字,然后对
进行排序
使用Collections.sort()列出。
但是我不确定如何用2种方式对其进行排序。
下面是我的代码,
public class SortAlphaNumeric {
static class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
String oo1 = o1.substring(3) + o1.substring(0,3);
String oo2 = o2.substring(3) + o2.substring(0,3);
return oo1.compareTo(oo2);
}
}
public static void main(String[] args) {
String str1 = "ABC123";
String str2 = "ACB111";
String str3 = "XXX003";
String str4 = "XYZ001";
String str5 = "CDE123";
String str6 = "FEG111";
List<String> list = new ArrayList<String>();
list.add(str1);
list.add(str2);
list.add(str3);
list.add(str4);
list.add(str5);
list.add(str6);
System.out.println("Before sorting");
Iterator<String> itr1 = list.iterator();
while(itr1.hasNext()) {
System.out.println(itr1.next());
}
SortAlphaNumeric.MyComparator myComp = new SortAlphaNumeric.MyComparator();
System.out.println("========================");
Collections.sort(list, myComp);
System.out.println("After 1st sorting");
Iterator<String> itr2 = list.iterator();
while(itr2.hasNext()) {
System.out.println(itr2.next());
}
Collections.sort(list, myComp);
System.out.println("After 2nd sorting");
Iterator<String> itr3 = list.iterator();
while(itr3.hasNext()) {
System.out.println(itr3.next());
}
}
}
答案 0 :(得分:2)
您可以轻松地组成两个比较器,将0-3
索引比较链接到3-6
索引比较上。
以下是使用子字符串而不是split
的替代方法(进一步简化了代码):
Comparator<String> myComp = Comparator.comparing((String s) -> s.substring(3))
.thenComparing(s -> s.substring(0, 3));
// resulting in:
// XYZ001, XXX003, ACB111, FEG111, ABC123, CDE123
假设文本具有此标准长度,则以上代码消除了对MyComparator
类的需要。
答案 1 :(得分:1)
如果您使用的是Java 8,则可以使用Comparator:
List<String> inputs = Arrays.asList(
"ABC123", "ACB111", "XXX003", "XYZ001", "CDE123", "FEG111"
);
inputs.sort(Comparator.comparing((String s) -> Integer.valueOf(s.split("(?<=\\D)(?=\\d)")[1]))
.thenComparing(s -> s.split("(?<=\\D)(?=\\d)")[0]));
System.out.println(inputs);
输出
[XYZ001, XXX003, ACB111, FEG111, ABC123, CDE123]
答案 2 :(得分:1)
正如您已经阐明的那样,您不想使用逻辑“按数字部分排序,如果相等,则按char部分排序”来进行一次排序,但是应该假定它是两种不同的排序。为此,您应该实现两个不同的比较器。
数值比较
只要所有字符串的长度和char-number-distribution相同,当前的逻辑(在索引3处分割并将数字与String
进行比较)就可以工作。但是,如果存在诸如“ ABC12”或“ A12345”之类的元素,则会遇到麻烦:首先,您将字符和数字混合在一起,然后,即使您设法正确地将它们分开(请阅读here如何做到),将数字与String
进行比较,如果它们的长度不同(例如2 <12,但“ 2”>“ 12”),则会导致错误的结果。您应该将数字解析为实际的整数,然后进行比较。这是用于此目的的比较器的外观:
Comparator<String> byNumber = Comparator.comparingInt(o -> Integer.parseInt(getNumberPart(o)));
// look at the linked question for how to properly split, a simple
// solution might use something like o.replaceAll("\\w", "")
字符串比较
至于char部分,这很简单:
Comparator<String> byChars = Comparator.comparing(o -> getCharPart(o));
现在,您可以使用它们根据需要对列表进行排序:
list.sort(byNumber); // XYZ001, XXX003, FEG111<->ACB111, ABC123<->CDE123
list.sort(byChars); // ACB111<->ABC123, CDE123, FEG111, XYZ003<->XXX001
请注意,由于仅按数字或字符进行比较,因此不确定如何对具有相同数字/字符部分的元素进行排序。例如,它可以根据并行性或基础集合进行更改。如果要确保始终有相同的顺序,可以将主比较器与第二个比较器组合,如果第一个返回0,则使用第二个比较器:
list.sort(byNumber.thenComparing(byChars)); // XYZ001, XXX003, ACB111, FEG111, ABC123, CDE123
list.sort(byChars.thenComparing(byNumber)); // ACB111, ABC123, CDE123, FEG111, XYZ001, XXX003