Java Поток сортировки списка строк в виде чисел - PullRequest
2 голосов
/ 13 февраля 2020

У меня проблема с сортировкой списка номеров вопросов в виде строк.

List<String> list = Arrays.asList("12.2", "12.1", "12.3", "12.4", "12.5", "12.10");

List<String> sortedList = list.stream().sorted().collect(Collectors.toList());

При распечатке sortedList я получаю:

12.1
12.10
12.2
12.3
12.4
12.5

Я пробовал следующее, но получал многоочаговые ошибки. Пожалуйста, помогите

.sorted(Comparator.comparingDouble(question ->(Double.parseDouble(question.getQuestionNumber()))  ))

Ответы [ 3 ]

4 голосов
/ 13 февраля 2020

String.compareСравнивает строки лексикографически. Цифры - это просто символы в таком сравнении, не отличающиеся от букв, знаков препинания или смайликов.

Вам нужен компаратор, который распознает формат nn . nn . Вы могли бы написать новый Comparator, но более управляемым подходом является наличие класса, который анализирует такие строки.

Если вы используете Java 9 или более позднюю версию, вам повезло: уже есть такой учебный класс. Этот класс Runtime.Version .

Таким образом, вы можете отсортировать строки, сравнив их соответствующие эквиваленты Runtime.Version, а затем преобразовав отсортированные объекты обратно в строки:

List<String> sortedList =
    list.stream().map(Runtime.Version::parse).sorted()
    .map(Object::toString).collect(Collectors.toList());
2 голосов
/ 13 февраля 2020

Как было написано в комментариях: вы можете объединить два Comparator сначала по длине, затем по String значению.

list.stream()
    .sorted(Comparator
            .comparing(String::length)
            .thenComparing(String::compareTo))
    .collect(Collectors.toList());

ОБНОВЛЕНИЕ

Как было написано Хольгером, есть некоторые проблемы с вышеуказанным подходом. Его можно переписать, как показано ниже:

list.stream()
    .sorted(Comparator.comparing((String s) -> s.split("\\."),
        Comparator
            .comparing((String[] a) -> Integer.parseInt(a[0]))
            .thenComparingInt((a) -> a.length > 1 ? Integer.parseInt(a[1]) : 0))
    )
    .collect(Collectors.toList());

Но это выглядит сложнее, и он делает более или менее то же самое, что было предложено VGR . Таким образом, в конце вы можете написать это так:

list.stream()
    .sorted(Comparator.comparing(Runtime.Version::parse))
    .collect(Collectors.toList());
0 голосов
/ 13 февраля 2020

Вы сортируете строку, ваш результат верен, если вы хотите отсортировать строку. Но в вашем случае вы должны преобразовать его в float, double, Double или BigDecimal ...

Попробуйте этот код:

List list = Arrays.asList("12.2", "12.1", "12.3", "12.4", "12.5", "12.10");

List sortedList = list.stream()**.map(Double::valueOf)**.sorted().collect(Collectors.toList());

Преобразовав это значение, вы получите правильный порядок для число.

...