繁体   English   中英

排序LinkedHashMap <String, String[]> .entrySet()由键组成,但在键中间使用正则表达式

[英]Sorting LinkedHashMap<String, String[]>.entrySet() by the keys, but in the middle of the keys using a regex

我有一个LinkedHashMap将字符串映射到字符串数组。

键的格式如下:“ xxx (yyy(0.123))

基本上,我希望能够对条目集进行排序,使其按小数部分而不是字符串的开头进行排序。 到目前为止,我所做的是将条目集转换为ArrayList,以便我可以尝试在其上调用Arrays.sort,但是显然这只是按字符串的开头进行排序。

我目前在想的是,我将必须遍历此数组,使用比较器将对中的每个键转换为自定义类,该比较器将我想要的方式进行比较(使用正则表达式.*\\((.*)\\)\\)以找到小数点)。 但是,这听起来似乎是很多不必要的开销,所以我想知道是否有更简单的方法。 提前致谢。

您的解决方案听起来不错。

如果遇到性能问题,则可以通过将字符串替换为包含字符串和十进制值的对象来缓冲十进制值。 然后,在排序期间无需多次重新计算。

上面提到的缓冲解决方案需要权衡取舍,弄清楚哪种技术最佳才是真正取决于整个解决方案的方法。

您是否需要使用LinkedHashMap的原因? Javadoc特别声明

此链表定义了迭代顺序,通常是将键插入映射的顺序(插入顺序)

TreeMap似乎更适合您要实现的目标,它使您可以在构造时提供Comparator 使用Java 8,可以通过以下方式实现:

private static final String DOUBLE_REGEX = "(?<value>\\d+(?:\\.\\d+)?)";
private static final String FIND_REGEX = "[^\\d]*\\(" + DOUBLE_REGEX + "\\)[^\\d]*";
private static final Pattern FIND_PATTERN = Pattern.compile(FIND_REGEX);

private static final Comparator<String> COMPARATOR = Comparator.comparingDouble(
    s -> {
        final Matcher matcher = FIND_PATTERN.matcher(s);
        if (!matcher.find()) {
            throw new IllegalArgumentException("Cannot compare key: " + s);
        }
        return Double.parseDouble(matcher.group("value"));
    });

private final Map<String, List<String>> map = new TreeMap<>(COMPARATOR);

编辑:如果必须是LinkedHashMapyours ),则可以始终:

map.putAll(yours);
yours.clear();
yours.putAll(map);

首先,您不能对LinkedHashMap “排序”。 LinkedHashMap根据插入顺序维护迭代顺序。

如果您LinkedHashMap通过使用原始地图中的值进行插入来创建另一个LinkedHashMap ,且其顺序基于已排序顺序:您需要知道在初始构造未排序后添加的任何新条目。 因此,您可能想创建一个不可修改的地图。

对于Comparator实施,您无需使其成为自定义类。 只需创建一个比较器就可以完成比较。

像这样:

(尚未编译,只是为了向您展示这个想法)

// assume the key is in format of "ABCDE,12345", and you want to sort by the numeric part:
Map<String, Foo> oldMap = ....; // assume you populated something in it
Map<String, Foo> sortedMap 
    = new TreeMap((a,b) -> {
                     // here I use split(), you can use regex
                     int aNum = Integer.valueOf(a.split(",")[1]);
                     int bNum = Integer.valueOf(b.split(",")[1]);
                     if (aNum != bNum )  {
                         return aNum - bNum;
                     } else {
                         return a.compareTo(b);
                     });
sortedMap.addAll(oldMap);
// now sortedMap contains your entries in sorted order.
// you may construct a new LinkedHashMap with it or do whatever you want

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM