Закажите карту, содержащую строку, но строки могут представлять число

У меня есть такие значения внутри карты:

Map<Integer, String> map = new HashMap<Integer, String>();                  
map.put(1,"mark");
map.put(2,"1.1");
map.put(3,"google");
map.put(4,"12");
map.put(5,"2.2);

Мне нужно заказать эту карту, заказав как числа, так и строки.

Теперь я получаю следующее (как вы можете видеть, числа не «упорядочены», так как это String)

1.1
12
2.2
google
mark

Что я должен получить:

1.1
2.2
12
google
mark

Как мне это сделать? Я немного запутался.

Что вы имеете ввиду под заказом карты? (HashMap не заказывается). Можете ли вы показать свой код?

user7 28.05.2019 17:13

сделать простой преобразователь, возвращающий Float.parse, если числовая строка, Float.MAX_VALUE в противном случае, и использовать компаратор на его основе

Alex Salauyou 28.05.2019 17:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы не можете заказать Map по значению входа. SortedMap например. TreeMap позволяет упорядочить записи по ключу. Кажется, вы можете использовать неправильную структуру данных.

В вашем примере вы можете определить функцию, которая будет снисходительно анализировать double и возвращать Double.NaN вместо исключения:

private double lenientParseDouble(String s) {
    try {
        return Double.parseDouble(s);
    } catch (NumberFormatException ex) {
        return Double.NaN;
    }
}

Согласно Double.compare() документам:

Double.NaN is considered by this method to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY).

а затем использовать его как часть цепочки Comparator

map.values().stream()
        .sorted(Comparator.comparingDouble(this::lenientParseDouble).thenComparing(Function.identity()))
        .forEach(System.out::println);

Спасибо чувак, работает. Я никогда не видел этот синтаксис. Мне нужно получить отсортированное значение (чтобы добавить их в список) вместо того, чтобы печатать их с помощью System.out? Спасибо

MDP 28.05.2019 20:33
Ответ принят как подходящий

Если вам действительно нужна карта, вы можете использовать LinkedHashMap, который отсортирован по порядку вставки. Для сравнения значений вы можете создать свой собственный компаратор:

Comparator<String> stringAndNumberComparator = (s1, s2) -> {
    try {
        return Double.valueOf(s1).compareTo(Double.valueOf(s2));
    } catch (NumberFormatException e) {
        return s1.compareTo(s2);
    }
};

Теперь вы можете использовать java-поток, чтобы отсортировать набор записей вашей карты и собрать его обратно в LinkedHashMap:

Map<Integer, String> sorted = map.entrySet().stream()
        .sorted(Map.Entry.comparingByValue(stringAndNumberComparator))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (s1, s2) -> s1, LinkedHashMap::new));

В качестве альтернативы вы можете использовать компаратор, предоставленный в ответ от Кароль Доубеки с Map.Entry.comparingByValue().

Результат будет {2=1.1, 5=2.2, 4=12, 3=google, 1=mark};

Если вам просто нужен список ваших значений, вы можете просто использовать это:

List<String> sorted = map.values().stream()
        .sorted(stringAndNumberComparator)
        .collect(Collectors.toList());

Результат в этом случае будет [1.1, 2.2, 12, google, mark].

Спасибо маааааааааааан. Я попробовал это, и это работает. :) Когда я не могу использовать .compareTo() , потому что s1 или s2 имеют значение null, какое значение я должен вернуть, чтобы не «испортить» отсортированную карту?

MDP 28.05.2019 21:19

@MDP Вы можете добавить нулевые проверки раньше. например if (s1 == null) return -1; if (s2 == null) return 1;, но вы получите Exception, используя Collectors.toMap(). См. stackoverflow.com/q/24630963/9662601 для получения дополнительной информации об этом. Другим вариантом может быть фильтрация ненулевых значений до или замена их ненулевыми значениями по умолчанию.

Samuel Philipp 28.05.2019 21:23

Другие вопросы по теме