@Wan-Derer
Зобанели на Хабре, волки́ ;((

Java, сортировка строк. Как правильно?

Приветствую! Столкнулся со странной проблемой. Описание и вопрос в коде:

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
// НО! Результат всё тот же - неправильная сортировка.
// Как сие можно объяснить и как подобные строки сортировать правильно?

    }
}


Подскажите что не так и как правильно :)
  • Вопрос задан
  • 4840 просмотров
Пригласить эксперта
Ответы на вопрос 3
zagayevskiy
@zagayevskiy Куратор тега Java
Android developer at Yandex
Всё они правильно сортируются, в лексикографическом порядке. Посимвольно, '1'<'2', значит "100" < "2".
Пиши компаратор, который будет считать строки числами. Ты примерно это и сделал (дико неоптимально), но ты сравниваешь не те символы. В случае со 100 и 2 ты сравниваешь их с нулевого символа, и всего один раз. Опять 1<2. Сравнивать так имеет только строки одинаковой длины, в противном случае больше та, у которой длина больше.
Ответ написан
Комментировать
@Emiral
Arrays.asList насколько я помню возвращает immutable array.
Ответ написан
azerphoenix
@azerphoenix Куратор тега Java
Java Software Engineer
Вот, 2 варианта сортировки:

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]


Все в целом сводится к тому, чтобы спарсить массив или список строк в массив или список строк, а затем отсортировать
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы