Answer the question
In order to leave comments, you need to log in
Java, string sorting. How right?
Greetings! Faced a strange problem. Description and question in code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test1825 {
public static void main(String[] args) {
// Есть несортированный массив строк, содержащих числовые окончания
// (для простоты оставил только сами числа)
// Хочу их вывести в порядке возрастания числа:
// 1, 2, 5, 6, 11, 15, 21, 25, 55
// Пробую сортировать:
String[] s = {"5", "2", "11", "1", "21", "55", "15", "25", "6"};
Arrays.sort(s);
System.out.println(Arrays.toString(s));
// Результат: [1, 11, 15, 2, 21, 25, 5, 55, 6]
// наверно, предсказуем, но пробую через коллекцию:
List<String > list = new ArrayList<>(Arrays.asList("5", "2", "11", "1", "21", "55", "15", "25", "6"));
list.sort(String::compareTo);
System.out.println(list);
// Результат тот же. Логично, ведь взят штатный компаратор от String.
// Хорошо! Пишу свой компаратор, учитывающий длину строки:
list = Arrays.asList("5", "2", "11", "1", "21", "55", "15", "25", "6");
list.sort((String a, String b) ->
{
//System.out.println(a + "| " + b + "|"); // контроль
int res = 0;
char[] arrA = a.toCharArray();
char[] arrB = b.toCharArray();
int end = Math.min(a.length(), b.length());
for (int i = 0; i < end; i++) {
res = arrA[i] - arrB[i];
if (res != 0) break;
}
if (res == 0) res = a.length() - b.length();
//System.out.println(res); // контроль
return res;
}
);
System.out.println(list);
// Если раскомментировать контрольный вывод: то видно что компаратор отрабатывает правильно,
// т.е. к примеру: 2 < 11
// НО! Результат всё тот же - неправильная сортировка.
// Как сие можно объяснить и как подобные строки сортировать правильно?
}
}
Answer the question
In order to leave comments, you need to log in
All of them are correctly sorted, in lexicographic order. Character by character, '1'<'2' means "100" < "2".
Write a comparator that will count strings as numbers. You roughly did this (wildly suboptimal), but you're comparing the wrong characters. In the case of 100 and 2, you're comparing them against the null character, and only once. Again 1<2. Compare like this only has strings of the same length, otherwise the one with the longer length is greater.
Here are 2 sort options:
public class Main {
private static String[] sArr = {"5", "2", "11", "1", "21", "55", "15", "25", "6"};
public static void main(String[] args) {
sortMethod1();
sortMethod2(sArr);
}
/**
* Метод парсит значения в целочисленный массив, а затем сортирует
*/
public static void sortMethod1() {
int[] intArr = Arrays.stream(sArr).mapToInt(Integer::parseInt).toArray();
Arrays.sort(intArr);
System.out.println(Arrays.toString(intArr));
}
/**
* Метод парсит массив строк в List. Затем заменяет (удаляет) нечисловые символы и сортирует
* @param strArr
*/
public static void sortMethod2(String[] strArr) {
List<String> stringList = Arrays.asList(strArr);
Collections.sort(stringList, new Comparator<String>() {
public int compare(String o1, String o2) {
return extractInt(o1) - extractInt(o2);
}
int extractInt(String s) {
String num = s.replaceAll("\\D", "");
return num.isEmpty() ? 0 : Integer.parseInt(num);
}
});
System.out.println(stringList);
}
}
[1, 2, 5, 6, 11, 15, 21, 25, 55]
[1, 2, 5, 6, 11, 15, 21, 25, 55]
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question