この文字列のリストがあります
Car1
Car2
Car3
......
Carn
このリストを数値に従って並べ替えたいと思います。
たとえば、 がある場合はCar3, Car1, Car12, Car45、 のように並べ替えCar1, Car3, Car12, Car45ます。
を使用Collections.sort()しましたが、 のようなものが返されますCar1, car12, car3, Car45。
正しい順序にするにはどうすればよいですか?
この文字列のリストがあります
Car1
Car2
Car3
......
Carn
このリストを数値に従って並べ替えたいと思います。
たとえば、 がある場合はCar3, Car1, Car12, Car45、 のように並べ替えCar1, Car3, Car12, Car45ます。
を使用Collections.sort()しましたが、 のようなものが返されますCar1, car12, car3, Car45。
正しい順序にするにはどうすればよいですか?
次のようなカスタム Comparator が必要です
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
int i1 = Integer.parseInt(s1.replaceAll("\\D", ""));
int i2 = Integer.parseInt(s2.replaceAll("\\D", ""));
return Integer.compare(i1, i2);
}
});
これを使って:
class ComparatorOfNumericString implements Comparator<String>{
public int compare(String string1, String string2) {
// TODO Auto-generated method stub
String a = string1.substring(3);
String b = string2.split(3);
return Integer.parseInt(a)-Integer.parseInt(b);
}
}
ソート時に、このコンパレータを次のように渡します。
Collections.sort(stringList,new ComparatorOfNumericString ());
文字列に必要な順序を定義するメソッドにカスタムを指定する必要がありComparator<String>ます。Collections.sort()
これは、文字列内の任意の位置の数値に対して機能し、数値のない文字列も処理します (自然順序付けによる通常の文字列比較に戻ります)。
final Pattern intsOnly = Pattern.compile("\\d+");
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(final String string1, final String string2) {
String int1 = null;
String int2 = null;
Matcher matcher1 = intsOnly.matcher(string1);
if (matcher1.find()) {
int1 = matcher1.group();
Matcher matcher2 = intsOnly.matcher(string2);
if (matcher2.find()) {
int2 = matcher2.group();
}
}
if (int1 == null || int2 == null) { return string1.compareTo(string2); }
return Integer.valueOf(int1).compareTo(Integer.valueOf(int2));
}
};
Collections.sort(strings, comparator);
もちろんこれは、Truck1 が Car2 の前に来ることを意味しますが、それがあなたの質問によるとあなたが望んでいた方法です。
更新: 上記の解決策では、Car6 が Truck6 の前に来ることは保証されません。等しい数の場合に自然な文字列の順序にもフォールバックしたい場合は、これを使用します。
final Pattern intsOnly = Pattern.compile("\\d+");
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(final String string1, final String string2) {
String int1 = null;
String int2 = null;
Matcher matcher1 = intsOnly.matcher(string1);
if (matcher1.find()) {
int1 = matcher1.group();
Matcher matcher2 = intsOnly.matcher(string2);
if (matcher2.find()) {
int2 = matcher2.group();
}
}
int result = 0;
if (int1 != null && int2 != null) {
result = Integer.valueOf(int1).compareTo(Integer.valueOf(int2));
}
if (result == 0) {
return string1.compareTo(string2);
}
else {
return result;
}
}
};
Collections.sort(strings, comparator);
並べ替えは辞書順であり、アルファベット順で 1 が 3 よりも小さく、比較演算子が次に来るものを無視するため、この順序になります。あなたがする必要があるのは、文字列に数字だけを残して「車」を切り取る独自の比較子を書くことです。次に、その数字の文字列表現を int に解析し、int を比較する必要があります (ソリューション )
sortコンパレータでのオーバーロードを使用する必要があります。次のコードは、特定の文字列 (CarXXX) 用です。
Collections.sort(carList, new Comparator<String>() {
public int compare(String s1, String s2) {
int t1 = Integer.parseInt(s1.substring(3));
int t2 = Integer.parseInt(s2.substring(3));
return t1 - t2;
}
});
Collections.sort() は正しいので、コンパレータを書くだけです:
public class testComp implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
int number1 = Integer.parseInt(o1.substring(3, o1.length()));
int number2 = Integer.parseInt(o2.substring(3, o2.length()));
if (number1 > number2) {
return -1;
} else {
return 1;
}
}
これはあなたのために働くでしょう。ただし、重複することはできません
String text = "Car3, Car1, Car12, Car45";
String[] str = text.split(", ");
Map<Integer,String> myMap=new HashMap<>();
int[] numOnly=new int[str.length];
for (int i = 0; i < str.length; i++) {
numOnly[i] = Integer.parseInt(str[i].replaceAll("\\D", ""));
myMap.put(numOnly[i],str[i]);
}
System.out.println(myMap.values());