如何使 Java TreeMap 通过某些比较器进行排序?

问题描述 投票:0回答:2

我有一个java TreeMap(现在我们称之为多重集,因为这就是我使用它的目的),我希望它按字符串的长度排序。我的意思是对于这样的代码:

// Imports
import java.util.Comparator;
import java.util.TreeMap;

class CompareLength implements Comparator<String> {
    public int compare(String string, String string_2) {
        return Integer.compare(string.length(), string_2.length());
    }
}

// More lines of code ...
TreeMap<String, Integer> multiset = new TreeMap<>(new CompareLength());
multiset.put("abc", 1);
multiset.put("x", 1);
multiset.put("yz", 1);

for (String string: multiset.keySet()) {
    System.out.print(string + " ");
}

System.out.println(multiset.containsKey("xyz") + " ");

输出为:x yz abc true

我希望它按长度排序,而不是完全改变TreeMap的比较器! 我该怎么做呢?我也希望它能够工作,无论比较器是什么、键类型、键、值、值类型等。

注意:我对java很陌生,因此产生了误解。

java comparator string-comparison treemap
2个回答
3
投票

正如您所意识到的,传递给

Comparator
TreeMap
不仅指定条目的 order,还指定哪些条目被认为是等效的(即
Comparator.compare()
返回 0 的条目)。

结论是,您根本不应该为任何两个字符串值返回 0,除非您希望将它们视为相同(在您的情况下,这似乎意味着它们是

equal
)。一个简单的方法是使用这样的比较器:

class CompareLength implements Comparator<String> {
    public int compare(String str1, String str2) {
        int result = Integer.compare(str1.legnth(), str2.length());
        if (result == 0) {
          result = str1.compareTo(str2);
        }
        return result;
    }
}

1
投票

Sauer的回答是正确的。

我们可以进一步改进该代码,使其更整洁、更清晰、更简洁。

Comparator
类具有使用 lambda 或方法引用创建
Comparator
实现的便捷方法。这里我们两者都用。

不要使用String#length

方法。该方法基于 char
 类型。自 Java 2 以来,
char
 类型已基本上被破坏,并且自 Java 5 以来已被遗留。作为 16 位值,
char
 在物理上无法表示大多数字符。因此,如果字符串包含 Unicode 中 
BMP 之外的任何字符,则
String#length
会失败,即大多数字符中的任何一个都会失败。相反,在 Java 中处理单个字符时,请使用 code point 整数。

我们声明我们的地图是更通用的接口

NavigableMap

而不是具体的类TreeMap

NavigableMap < String, Integer > map = new TreeMap<>( Comparator .comparing( ( String s ) -> s.codePoints().count() ) .thenComparing( String :: compareTo ) );
定义一些示例数据。我们添加了更多条目,而不是显示具有相同字符串长度的多个键。

Java 9+ 中的

Map.of

 方法是一种以文字方式定义不可修改映射的简短而甜蜜的方法。我们将该地图作为参数传递来填充我们的 
TreeMap
    map.putAll( 
        Map.of (
            "abc" , 1 ,
            "x" , 2 ,
            "b" , 3 ,
            "a" , 4 ,
            "yz" , 5
        )
    ) ;

转储到控制台。

System.out.println( map ) ;

查看此代码
在 Ideone.com 上实时运行

{a=4, b=3, x=2, yz=5, abc=1}

© www.soinside.com 2019 - 2024. All rights reserved.