我在 Map 中有这样的值:
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);
我需要订购这个地图,对数字和字符串进行排序。
我现在得到的是这个(如您所见,数字不是"排序"的,因为是字符串(
1.1
12
2.2
google
mark
我应该得到的是:
1.1
2.2
12
google
mark
我该怎么做?我有点困惑。
不能按条目值对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
等于自身且大于所有其他双精度值(包括Double.POSITIVE_INFINITY
(。
然后将其用作Comparator
链的一部分
map.values().stream()
.sorted(Comparator.comparingDouble(this::lenientParseDouble).thenComparing(Function.identity()))
.forEach(System.out::println);
如果您确实需要地图,则可以使用按广告顺序排序的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));
或者,您可以使用卡罗尔·多贝基(Karol Dowbecki(的答案中提供的比较器与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]
.