По сути, у меня есть 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")))));
Это не очень хорошая идея, поскольку числа не отсортированы должным образом.... Как я могу справиться с этим?




Вы можете обобщить сравнение чисел, сравнив их двойные значения, потому что они самые большие. Если два объекта не могут быть приведены к числам и значение 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));
}
});