Java中的TreeMap用于存储键值对,非常类似于HashMap类。不同之处在于,TreeMap提供了一种高效的方式来按排序顺序存储键/值对。它是基于红黑树的NavigableMap实现。

在这个Java TreeMap教程中,我们将学习TreeMap类、它的方法、用途以及其他重要细节。

1.TreeMap层次结构

在Java中,TreeMap类的声明如下。它扩展了AbstractMap类并实现了NavigableMap接口。这里的 ‘K’ 是键的类型,’V’ 是键的映射值的类型。

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

2.TreeMap特点

关于Java TreeMap类的重要点有:

  • 它存储键值对,类似于HashMap。
  • 它只允许不同的键。重复的键是不可能的。
  • 它不能具有空键,但可以具有多个空值。
  • 它以排序顺序(自然顺序)或在映射创建时提供的比较器的方式存储键。
  • 对于containsKey、get、put和remove操作,它提供了确保的log(n)时间成本。
  • 它不是同步的。在并发环境中使用Collections.synchronizedSortedMap(new TreeMap())来工作。

3.TreeMap构造函数

TreeMap有五种类型的构造函数:

  • TreeMap():创建一个新的空树映射,使用其键的自然排序。
  • TreeMap(Comparator c):创建一个新的空树映射,根据给定的比较器进行排序。
  • TreeMap(Map map):创建一个包含与给定映射相同的映射的新树映射,根据其键的自然排序进行排序。
  • TreeMap(SortedMap map):创建一个包含与指定的已排序映射相同的映射,并使用相同的排序方式的新树映射。

4.TreeMap方法

我们应该了解的TreeMap的重要方法如下:

  • void clear():从映射中删除所有键值对。
  • int size():返回映射中存在的键值对的数量。
  • boolean isEmpty():如果此映射不包含键值映射,则返回true。
  • boolean containsKey(Object key):如果映射中存在指定的键,则返回’true’。
  • boolean containsValue(Object key):如果指定值映射到映射中的至少一个键,则返回’true’。
  • Object get(Object key):检索由指定键映射的值,如果此映射不包含键的映射,则返回null。
  • Object remove(Object key):如果存在,从映射中删除指定键的键值对。
  • Comparator comparator():返回用于按键在此映射中排序的比较器,如果此映射使用其键的自然排序,则返回null。
  • Object firstKey():返回树映射中当前的第一个(最小)键。
  • Object lastKey():返回树映射中当前的最后一个(最大)键。
  • Object ceilingKey(Object key):返回大于或等于给定键的最小键,如果没有这样的键,则返回null。
  • Object higherKey(Object key):返回严格大于指定键的最小键。
  • NavigableMap descendingMap():返回包含在此映射中包含的映射的反向顺序视图。

5.Java TreeMap示例

5.1. 使用自然排序的TreeMap示例

Java程序演示了使用自然排序的TreeMap方法的用法。

import java.util.Iterator; import java.util.TreeMap; public class LinkedHashMapExample { public static void main(String[] args) { //默认自然排序 TreeMap<Integer, String> pairs = new TreeMap<>(); pairs.put(2, "B"); pairs.put(1, "A"); pairs.put(3, "C"); String value = pairs.get(3); //获取方法 System.out.println(value); value = pairs.getOrDefault(5, "oops"); //getOrDefault 方法 System.out.println(value); //迭代示例 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 方法 System.out.println(pairs.containsValue("B")); //containsValue 方法 System.out.println(pairs.ceilingKey(2)); } } 

输出:

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

5.2. 使用Comparator进行自定义排序的TreeMap示例

import java.util.Iterator; import java.util.TreeMap; public class LinkedHashMapExample { public static void main(String[] args) { //对key进行逆序排序 TreeMap<Integer, String> pairs = new TreeMap<>(Collections.reverseOrder()); pairs.put(2, "B" ); pairs.put(1, "A"); pairs.put(3, "C"); System.out.println(pairs);// {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都不是同步的,程序员需要在Map上管理并发访问。

我们可以显式地获得树映射的同步视图,使用Collections.synchronizedSortedMap(new TreeMap())。

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相关的问题。