如何在 Java 中为 TreeMap 编写自定义比较器?
How to write a custom Comparator for TreeMap in Java?
我想在 TreeMap 中存储键值对,并按照以下逻辑根据 Key 的值对条目进行排序:
按键的长度排序。如果两个键的长度相同,则按字母顺序对它们进行排序。例如,对于以下键值对。
IBARAKI MitoCity
TOCHIGI UtunomiyaCity
GUNMA MaehashiCity
SAITAMA SaitamaCity
CHIBA ChibaCity
TOKYO Sinjyuku
KANAGAWA YokohamaCity
预期的输出是这样的。
CHIBA : ChibaCity
GUNMA : MaehashiCity
TOKYO : Sinjyuku
IBARAKI : MitoCity
SAITAMA : SaitamaCity
TOCHIGI : UtunomiyaCity
KANAGAWA : YokohamaCity
您需要为此编写自己的 comparator
并在 TreeMap
中使用它,例如:
public class StringComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
return s1.length() == s2.length() ? s1.compareTo(s2) : s1.length() - s2.length();
}
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
Map<String, String> map = new TreeMap<>(new StringComparator());
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
}
这不会处理 null
值,但如果您希望在用例中使用 null
值,则可以添加处理。
您可以将 Comparator 作为参数传递给 Map 的构造函数。
根据文档,它仅用于键:
/**
* Constructs a new, empty tree map, ordered according to the given
* comparator. All keys inserted into the map must be <em>mutually
* comparable</em> by the given comparator: {@code comparator.compare(k1,
* k2)} must not throw a {@code ClassCastException} for any keys
* {@code k1} and {@code k2} in the map. If the user attempts to put
* a key into the map that violates this constraint, the {@code put(Object
* key, Object value)} call will throw a
* {@code ClassCastException}.
*
* @param comparator the comparator that will be used to order this map.
* If {@code null}, the {@linkplain Comparable natural
* ordering} of the keys will be used.
*/
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
通过这种方式,您可以像这样按密钥长度传递比较器:
new TreeMap<>(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
您应该创建一个唯一的比较器来比较地图的键。但是因为您也想打印这些值,所以您应该比较整个条目集:
Comparator<Map.Entry<String, String>> c = new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
int q = Integer.compare(o1.getKey().length(), o2.getKey().length());
return q != 0 ? q : o1.getKey().compareTo(o2.getKey());
}
};
那么你可以在排序中使用这个比较器:
map.entrySet().stream().sorted(c).forEach(System.out::println);
您可以按如下方式进行。
public static void main(String[] args) {
Map<String, String> map = new TreeMap<>(new CustomSortComparator());
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
CustomSortComparator 定义如下。
public class CustomSortComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1.length() > o2.length()) {
return 1;
}
if (o1.length() < o2.length()) {
return -1;
}
return returnCompareBytes(o1, o2);
}
private int returnCompareBytes(String key1, String key2) {
for (int i = 0; i < key1.length() - 1; i++) {
if (key1.charAt(i) > key2.charAt(i)) {
return 1;
}
if (key1.charAt(i) < key2.charAt(i)) {
return -1;
}
}
return 0;
}
}
您可以使用此方法代替直接将 Map 转换为 TreeMap
public static Map toTreeMap(Map hashMap)
{
// Create a new TreeMap
Map treeMap = new TreeMap<>(new Comparator<Map.Entry<String, String>>(){
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2 )
{
if (o1.getKey().length() > o2.getKey().length()) {
return 1;
}
if (o1.getKey().length() > o2.getKey().length()) {
return -1;
}
return o1.getKey().compareTo(o2.getKey());
}
});
for(Map.entry e : hashmap){
treeMap.put(e.getKey(),e.getValue);
}
return treeMap;
}
您可以在 TreeMap
的构造函数调用中定义您需要的 Comparator<String>
:
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
public class Main {
static final Map<String, String> map =
new TreeMap<String, String> (new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int diff_length = o1.length() - o2.length();
if (diff_length != 0) return diff_length;
return o1.compareTo(o2);
}
});
public static final void main(String[] args) {
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
}
我想在 TreeMap 中存储键值对,并按照以下逻辑根据 Key 的值对条目进行排序:
按键的长度排序。如果两个键的长度相同,则按字母顺序对它们进行排序。例如,对于以下键值对。
IBARAKI MitoCity
TOCHIGI UtunomiyaCity
GUNMA MaehashiCity
SAITAMA SaitamaCity
CHIBA ChibaCity
TOKYO Sinjyuku
KANAGAWA YokohamaCity
预期的输出是这样的。
CHIBA : ChibaCity
GUNMA : MaehashiCity
TOKYO : Sinjyuku
IBARAKI : MitoCity
SAITAMA : SaitamaCity
TOCHIGI : UtunomiyaCity
KANAGAWA : YokohamaCity
您需要为此编写自己的 comparator
并在 TreeMap
中使用它,例如:
public class StringComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
return s1.length() == s2.length() ? s1.compareTo(s2) : s1.length() - s2.length();
}
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
Map<String, String> map = new TreeMap<>(new StringComparator());
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
}
这不会处理 null
值,但如果您希望在用例中使用 null
值,则可以添加处理。
您可以将 Comparator 作为参数传递给 Map 的构造函数。 根据文档,它仅用于键:
/**
* Constructs a new, empty tree map, ordered according to the given
* comparator. All keys inserted into the map must be <em>mutually
* comparable</em> by the given comparator: {@code comparator.compare(k1,
* k2)} must not throw a {@code ClassCastException} for any keys
* {@code k1} and {@code k2} in the map. If the user attempts to put
* a key into the map that violates this constraint, the {@code put(Object
* key, Object value)} call will throw a
* {@code ClassCastException}.
*
* @param comparator the comparator that will be used to order this map.
* If {@code null}, the {@linkplain Comparable natural
* ordering} of the keys will be used.
*/
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
通过这种方式,您可以像这样按密钥长度传递比较器:
new TreeMap<>(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
您应该创建一个唯一的比较器来比较地图的键。但是因为您也想打印这些值,所以您应该比较整个条目集:
Comparator<Map.Entry<String, String>> c = new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
int q = Integer.compare(o1.getKey().length(), o2.getKey().length());
return q != 0 ? q : o1.getKey().compareTo(o2.getKey());
}
};
那么你可以在排序中使用这个比较器:
map.entrySet().stream().sorted(c).forEach(System.out::println);
您可以按如下方式进行。
public static void main(String[] args) {
Map<String, String> map = new TreeMap<>(new CustomSortComparator());
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
CustomSortComparator 定义如下。
public class CustomSortComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1.length() > o2.length()) {
return 1;
}
if (o1.length() < o2.length()) {
return -1;
}
return returnCompareBytes(o1, o2);
}
private int returnCompareBytes(String key1, String key2) {
for (int i = 0; i < key1.length() - 1; i++) {
if (key1.charAt(i) > key2.charAt(i)) {
return 1;
}
if (key1.charAt(i) < key2.charAt(i)) {
return -1;
}
}
return 0;
}
}
您可以使用此方法代替直接将 Map 转换为 TreeMap
public static Map toTreeMap(Map hashMap)
{
// Create a new TreeMap
Map treeMap = new TreeMap<>(new Comparator<Map.Entry<String, String>>(){
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2 )
{
if (o1.getKey().length() > o2.getKey().length()) {
return 1;
}
if (o1.getKey().length() > o2.getKey().length()) {
return -1;
}
return o1.getKey().compareTo(o2.getKey());
}
});
for(Map.entry e : hashmap){
treeMap.put(e.getKey(),e.getValue);
}
return treeMap;
}
您可以在 TreeMap
的构造函数调用中定义您需要的 Comparator<String>
:
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
public class Main {
static final Map<String, String> map =
new TreeMap<String, String> (new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int diff_length = o1.length() - o2.length();
if (diff_length != 0) return diff_length;
return o1.compareTo(o2);
}
});
public static final void main(String[] args) {
map.put("IBARAKI", "MitoCity");
map.put("TOCHIGI", "UtunomiyaCity");
map.put("GUNMA", "MaehashiCity");
map.put("SAITAMA", "SaitamaCity");
map.put("CHIBA", "ChibaCity");
map.put("TOKYO", "Sinjyuku");
map.put("KANAGAWA", "YokohamaCity");
System.out.println(map);
}
}