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