Сортировка List<Map<String,Object>> по значению

По сути, у меня есть List<Map<String,Object>>, и я хочу отсортировать его по значениям определенного ключа на карте.

Проблема в том, что я не знаю тип... Эта карта может содержать строки, целые числа, двойные числа, числа с плавающей запятой и т.д.... Я хотел бы отсортировать ее:

До сих пор

List<Map<String,Object>> data = getResults();
Collections.sort(data, (o1, o2) -> (String.valueOf(o2.get("Field1")))
              .compareTo((String.valueOf(o1.get("Field1")))));

Это не очень хорошая идея, поскольку числа не отсортированы должным образом.... Как я могу справиться с этим?

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

Ответы 2

Ответ принят как подходящий

Вы можете обобщить сравнение чисел, сравнив их двойные значения, потому что они самые большие. Если два объекта не могут быть приведены к числам и значение double не может быть проанализировано из этих объектов, то сравните их строковые значения:

List<Map<String, Object>> data = Arrays.asList(
        Map.of("Field1", 21.2d),  // Double
        Map.of("Field1", "qqq"),  // String
        Map.of("Field1", "22.5"), // String
        Map.of("Field1", 2),      // Integer
        Map.of("Field1", 3L),     // Long
        Map.of("Field1", 23.1f)); // Float
data.sort(Comparator.comparingDouble((Map<String, Object> map) -> {
    Object object = map.get("Field1");
    if (object instanceof Number) {
        return ((Number) object).doubleValue();
    } else {
        try {
            return Double.parseDouble(String.valueOf(object));
        } catch (NumberFormatException e) {
            return Double.NaN;
        }
    }
}).thenComparing(map -> String.valueOf(map.get("Field1"))));
data.forEach(System.out::println);
// {Field1=2}
// {Field1=3}
// {Field1=21.2}
// {Field1=22.5}
// {Field1=23.1}
// {Field1=qqq}

See also: Sort 2D List by Column Header

Я думаю, что все значения на карте должны быть экземплярами Comparable, поэтому что-то вроде этого может работать. Это решение может быть лучше, чем принятый ответ, поскольку вы можете поместить свой собственный класс в качестве значений (например, MyClass, который реализует Comparable)

List<Map<String, Object>> data = getResults();

Collections.sort(data, (o1, o2) -> {
    Object v1 = o1.get("Field1");
    Object v2 = o2.get("Field1");
    if (v1 instanceof Comparable) {
        // may throw exception if v1 and v2 are not
        // the same type, eg Double compare String
        return ((Comparable) v1).compareTo((Comparable) v2);
    } else {
        return String.valueOf(v1).compareTo(String.valueOf(v2));
    }
});

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