订购包含字符串的地图,但字符串可能表示一个数字



我在 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] .

最新更新