# Java `TreeMap`类

> 原文： [https://howtodoinjava.com/java/collections/treemap-class/](https://howtodoinjava.com/java/collections/treemap-class/)

Java 中的`TreeMap`用于存储非常类似于[`HashMap`](https://howtodoinjava.com/java-hashmap/)类的键值对。 区别在于`TreeMap`提供了一种有效的方式来**以排序的顺序**存储键/值对。 这是基于**红黑树**的`NavigableMap`实现。

在本 **Java `TreeMap`教程**中，我们将学习`TreeMap`类，其方法，用例和其他重要细节。

```java
Table of Contents

1\. TreeMap Hierarchy
2\. TreeMap Features
3\. TreeMap Constructors
4\. TreeMap Methods
5\. TreeMap Example
6\. TreeMap Usecases
7\. TreeMap Performance
8\. Concurrency in TreeMap
9\. Conclusion
```

## 1\. `TreeMap`层次结构

在 Java 中，`TreeMap`类的声明如下。 它扩展了`AbstractMap`类，并且实现了`NavigableMap`接口。 `'K'`是键的类型，`'V'`是键的映射值的类型。

```java
public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
	//implementation
}

```

## 2\. `TreeMap`特性

关于 Java `TreeMap`类的要点是：

*   它存储类似于`HashMap`的键/值对。
*   它仅允许不同的键。 重复的密钥是不可能的。
*   它不能具有`null`键，但是可以具有多个`null`值。
*   它按排序顺序（自然顺序）或在映射创建时提供的[`Comparator`](https://howtodoinjava.com/sort/sort-arraylist-objects-comparable-comparator/)存储键。
*   它为`containsKey`，`get`，`put`和`remove`操作提供了有保证的`log(n)`时间成本。
*   它不是[同步的](https://howtodoinjava.com/java/multi-threading/what-is-thread-safety/)。 使用`Collections.synchronizedSortedMap(new TreeMap())`在并发环境中工作。
*   通过`iterator`方法返回的迭代器是**快速失败**。

## 3\. `TreeMap`构造器

`TreeMap`具有五种构造器：

1.  **`TreeMap()`**：使用其键的自然顺序创建一个新的空树映射。
2.  **`TreeMap(Comparator c)`**：创建一个新的空树映射，根据给定的比较器排序。
3.  **`TreeMap(Map map)`**：创建一个新的树映射，其中包含与给定映射相同的映射，并根据其键的自然顺序进行排序。
4.  **`TreeMap(SortedMap map)`**：创建一个新的树映射，其中包含与指定的已排序映射相同的映射并使用相同的顺序。

## 4\. `TreeMap`方法

我们应该了解的有关`TreeMap`的重要方法如下：

1.  **`void clear()`**：它将从映射中删除所有键值对。
2.  **`void size()`**：它返回此映射中存在的键/值对的数量。
3.  **`void isEmpty()`**：如果此映射不包含键值映射，则返回`true`。
4.  **`boolean containsKey(Object key)`**：如果映射中存在指定的键，则返回`'true'`。
5.  **`boolean containsValue(Object key)`**：如果将指定值映射到映射中的至少一个键，则返回`'true'`。
6.  **`Object get(Object key)`**：它检索由指定的`key`映射的`value`，如果此映射不包含该键的映射，则返回`null`。
7.  **`Object remove(Object key)`**：如果存在，它将从映射中删除指定键的键值对。
8.  **`Comparator comparator()`**：它返回用于对映射中的键进行排序的比较器；如果此映射使用其键的自然顺序，则返回 null。
9.  **`Object firstKey()`**：返回树图中当前的第一个（最小）键。
10.  **`Object lastKey()`**：返回树图中当前的最后一个（最大）键。
11.  **`Object ceilingKey(Object key)`**：它返回大于或等于给定键的最小键；如果没有这样的键，则返回`null`。
12.  **`Object HigherKey(Object key)`**：返回严格大于指定键的最小键。
13.  **`NavigableMapDescendingMap()`**：它返回此映射中包含的映射的**逆序视图**。

## 5\. Java `TreeMap`示例

#### 5.1 自然排序的`TreeMap`示例

Java 程序，以自然顺序演示`TreeMap`方法的用法。

```java
import java.util.Iterator;
import java.util.TreeMap;

public class LinkedHashMapExample 
{
    public static void main(String[] args) 
    {
        //Natual ordering by deafult
        TreeMap<Integer, String> pairs = new TreeMap<>();

        pairs.put(2,  "B");
        pairs.put(1,  "A");
        pairs.put(3,  "C");

        String value = pairs.get(3);    //get method

        System.out.println(value);

        value = pairs.getOrDefault(5, "oops");  //getOrDefault method

        System.out.println(value);

        //Iteration example
        Iterator<Integer> iterator =  pairs.keySet().iterator();

        while(iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.println("Key: " + key + ", Value: " + pairs.get(key));
        }

        //Remove example
        pairs.remove(3);
        System.out.println(pairs);

        System.out.println(pairs.containsKey(1));    //containsKey method   

        System.out.println(pairs.containsValue("B"));    //containsValue method   

        System.out.println(pairs.ceilingKey(2));
    }
}

```

程序输出。

```java
C
oops
Key: 1, Value: A
Key: 2, Value: B
Key: 3, Value: C
{1=A, 2=B}
true
true
2

```

#### 5.2 使用比较器自定义顺序的`TreeMap`示例

```java
import java.util.Iterator;
import java.util.TreeMap;

public class LinkedHashMapExample 
{
    public static void main(String[] args) 
    {
    	//Sort keys in reverse order
        TreeMap<Integer, String> pairs = new TreeMap<>(Collections.reverseOrder());

        pairs.put(2,  "B" );
        pairs.put(1,  "A");
        pairs.put(3,  "C");

        System.out.println(pairs);
    }
}

```

程序输出：

```java
{3=C, 2=B, 1=A}

```

## 6\. `TreeMap`用例

无论是使用默认排序还是使用比较器进行自定义排序，`TreeMap`都提供了一种有效的方法来以排序的方式存储和检索其中包含的信息。 这使其成为在需要按顺序显示信息的情况下使用的出色工具。 例如，在任何移动应用程序中，员工基于其年龄或电话号码的信息。

另一个有用的用例可以是字典，在字典中以分类的方式记录和显示信息。

实际上，它们在需要对信息进行分类并且需要快速随机访问的任何地方都非常有用。 如果不需要随机访问，则使用排序集或列表。

## 7\. `TreeMap`的性能

`TreeMap`为大多数操作（如`add()`，`remove()`和`contains()`）提供`log(n)`的性能。 `HashMap`对于相同的操作执行时性能为`O(1)`。 这样，`HashMap`的性能就比`TreeMap`好得多。

`TreeMap`在内存管理中具有更好的性能，因为它不在内部维护数组来存储键值对。 在`HashMap`中，数组大小是在初始化或调整大小时确定的，如果确定大小通常超过当时的需要。 它浪费了内存。 `TreeMap`没有这种问题。

## 8\. `TreeMap`中的并发

`Map`，`HashMap`和`TreeMap`的两个版本均未同步，程序员需要管理对映射的并发访问。

我们可以使用`Collections.synchronizedSortedMap(new TreeMap())`明确获取树图的同步视图。

```java
Map<Integer, String> syncTreeMap = Collections.synchronizedSortedMap(new TreeMap<Integer, String>());

syncTreeMap.put(1,  "A");
syncTreeMap.put(2,  "B" );
syncTreeMap.put(3,  "C");

```

## 9\. 总结

在本教程中，我们了解了 Java `TreeMap`类及其内部。 我们看到了它如何以自然方式（默认）或某些自定义键顺序（使用提供的比较器）以排序方式存储键值对。

我们讨论了在实时应用程序中应如何以及何时使用`TreeMap`。 我们将`TreeMap`和`HashMap`的性能进行了比较，以更好地了解何时使用哪个版本的`Map`。

在注释部分中，将您有关在 Java 中使用`TreeMap`的问题提供给我。

学习愉快！

参考：

[`TreeMap` Java 文档](https://docs.oracle.com/javase/10/docs/api/java/util/TreeMap.html)