我有一个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很陌生,因此产生了误解。
正如您所意识到的,传递给
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;
}
}
Sauer的回答是正确的。
我们可以进一步改进该代码,使其更整洁、更清晰、更简洁。
Comparator
类具有使用 lambda 或方法引用创建 Comparator
实现的便捷方法。这里我们两者都用。
不要使用String#length
char
类型。自 Java 2 以来,
char
类型已基本上被破坏,并且自 Java 5 以来已被遗留。作为 16 位值,
char
在物理上无法表示大多数字符。因此,如果字符串包含 Unicode 中BMP 之外的任何字符,则
String#length
会失败,即大多数字符中的任何一个都会失败。相反,在 Java 中处理单个字符时,请使用 code point 整数。
我们声明我们的地图是更通用的接口而不是具体的类TreeMap
。
NavigableMap < String, Integer > map =
new TreeMap<>(
Comparator
.comparing( ( String s ) -> s.codePoints().count() )
.thenComparing( String :: compareTo )
);
定义一些示例数据。我们添加了更多条目,而不是显示具有相同字符串长度的多个键。Java 9+ 中的
方法是一种以文字方式定义不可修改映射的简短而甜蜜的方法。我们将该地图作为参数传递来填充我们的
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}