# 面试了十个应届生九个都没用过TreeMap，你确定你们是个 Java 程序员？(2)

### 01、自然顺序

TreeMap<Integer,String> mapInt = new TreeMap<>();
mapInt.put(3, "沉默王二");
mapInt.put(2, "沉默王二");
mapInt.put(1, "沉默王二");
mapInt.put(5, "沉默王二");
mapInt.put(4, "沉默王二");
System.out.println(mapInt);

{1=沉默王二, 2=沉默王二, 3=沉默王二, 4=沉默王二, 5=沉默王二}

1

TreeMap 是怎么做到的呢？想一探究竟，就得上源码了，来看 TreeMap 的 put() 方法（省去了一部分，版本为 JDK 14）：

public V put(K key, V value) {
TreeMap.Entry<K,V> t = root;
int cmp;
TreeMap.Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
}
else {
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
return null;
}

public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

public int compareTo(String anotherString) {
byte v1[] = value;
byte v2[] = anotherString.value;
byte coder = coder();
if (coder == anotherString.coder()) {
return coder == LATIN1 ? StringLatin1.compareTo(v1, v2)
: StringUTF16.compareTo(v1, v2);
}
return coder == LATIN1 ? StringLatin1.compareToUTF16(v1, v2)
: StringUTF16.compareToLatin1(v1, v2);
}

TreeMap<String,String> mapString = new TreeMap<>();
mapString.put("c", "沉默王二");
mapString.put("b", "沉默王二");
mapString.put("a", "沉默王二");
mapString.put("e", "沉默王二");
mapString.put("d", "沉默王二");
System.out.println(mapString);

{a=沉默王二, b=沉默王二, c=沉默王二, d=沉默王二, e=沉默王二}

1

### 02、自定义排序

TreeMap<Integer,String> mapIntReverse = new TreeMap<>(Comparator.reverseOrder());

mapIntReverse.put(3, "沉默王二");

mapIntReverse.put(2, "沉默王二");

mapIntReverse.put(1, "沉默王二");

mapIntReverse.put(5, "沉默王二");

mapIntReverse.put(4, "沉默王二");

System.out.println(mapIntReverse);

TreeMap 提供了可以指定排序规则的构造方法：

public TreeMap(Comparator<? super K> comparator) {

this.comparator = comparator;

}

Comparator.reverseOrder() 返回的是 ReverseComparator 对象，就是用来反转顺序的，非常方便。

{5=沉默王二, 4=沉默王二, 3=沉默王二, 2=沉默王二, 1=沉默王二}

1

HashMap 是无序的，插入的顺序随着元素的增加会不停地变动。但 TreeMap 能够至始至终按照指定的顺序排列，这对于需要自定义排序的场景，实在是太有用了！

### 03、排序的好处

Integer highestKey = mapInt.lastKey();
Integer lowestKey = mapInt.firstKey();
Set<Integer> keysGreaterThanEqTo3 = mapInt.tailMap(3).keySet();
System.out.println(highestKey);
System.out.println(lowestKey);
System.out.println(keysLessThan3);
System.out.println(keysGreaterThanEqTo3);

TreeMap 考虑得很周全，恰好就提供了 lastKey()、firstKey() 这样获取最后一个 key 和第一个 key 的方法。

headMap() 获取的是到指定 key 之前的 key；tailMap() 获取的是指定 key 之后的 key（包括指定 key）。

5

1

[1, 2]

[3, 4, 5]

### 04、如何选择 Map

HashMap 完全不保证元素的顺序，添加了新的元素，之前的顺序可能完全逆转。

TreeMap 默认会保持 key 的自然顺序（根据 compareTo() 方法）。

|
1天前
|

Java分布式技术面试总结（全面，实时更新）
Java分布式技术面试总结（全面，实时更新）
20 2
|
1天前
|

Java微服务框架面试总结（全面，实时更新）
Java微服务框架面试总结（全面，实时更新）
11 2
|
1天前
|

Java技术栈Redis面试总结（全面，实时更新）
Java技术栈Redis面试总结（全面，实时更新）
15 2
|
1天前
|

Java高级进阶面试总结（全面，实时更新）
Java高级进阶面试总结（全面，实时更新）
18 1
|
3天前
|

23 0
|
SQL 缓存 安全
Java高频面试题目

105 0
JAVA高频面试题目集锦（6）
JAVA高频面试题目集锦（6）
108 0
|

JAVA高频面试题目集锦（5）
JAVA高频面试题目集锦（5）
153 0
|

JAVA高频面试题目集锦（4）
JAVA高频面试题目集锦（4）
85 0
|

JAVA高频面试题目集锦（3）
JAVA高频面试题目集锦（3）
95 0