跳到主要内容

Java TreeMap 类

提示
  1. TreeMap基本概念TreeMap类在Java集合框架中实现树形数据结构,提供元素的自然排序(升序)功能。
  2. TreeMap的元素插入和访问方法TreeMap允许使用put()插入键值对、get()访问元素,以及entrySet(), keySet(), 和 values()方法遍历映射。
  3. TreeMap的导航方法:提供firstKey(), lastKey(), higherKey(), lowerKey(), ceilingKey(), floorKey()等方法来导航和操作键值对,支持根据键的顺序获取和处理元素。

Java 集合框架中的 TreeMap 类提供了树形数据结构的实现。

它实现了 NavigableMap 接口

Java TreeMap 类实现了 Map 接口。

创建 TreeMap

要创建一个 TreeMap,我们首先需要导入 java.util.TreeMap 包。导入包后,我们就可以用以下方式在 Java 中创建一个 TreeMap

TreeMap<Key, Value> numbers = new TreeMap<>();

在上面的代码中,我们创建了一个名为 numbersTreeMap,没有传入任何参数。在这种情况下,TreeMap 中的元素会自然排序(升序)。

然而,我们可以通过使用 Comparator 接口来自定义元素的排序。我们将在本教程后面学习这一点。

这里,

  • Key - 用于将每个元素(值)与映射中的键相关联的唯一标识符
  • Value - 映射中键所关联的元素

TreeMap 的方法

TreeMap 类提供了多种方法,允许我们对映射执行操作。

向 TreeMap 插入元素

  • put() - 向映射中插入指定的键/值映射(条目)
  • putAll() - 将指定映射中的所有条目插入到此映射中
  • putIfAbsent() - 如果指定的键在映射中不存在,则向映射中插入指定的键/值映射

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {
// 创建偶数的 TreeMap
TreeMap<String, Integer> evenNumbers = new TreeMap<>();

// 使用 put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);

// 使用 putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("偶数的 TreeMap: " + evenNumbers);

// 创建数字的 TreeMap
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);

// 使用 putAll()
numbers.putAll(evenNumbers);
System.out.println("数字的 TreeMap: " + numbers);
}
}

输出

偶数的 TreeMap: {Four=4, Six=6, Two=2}
数字的 TreeMap: {Four=4, One=1, Six=6, Two=2}

访问 TreeMap 元素

1. 使用 entrySet(), keySet() 和 values()

  • entrySet() - 返回 treemap 的所有键/值映射(条目)的集合
  • keySet() - 返回 tree map 的所有键的集合
  • values() - 返回 tree map 的所有值的集合

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();

numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// 使用 entrySet()
System.out.println("键/值映射: " + numbers.entrySet());

// 使用 keySet()
System.out.println("键: " + numbers.keySet());

// 使用 values()
System.out.println("值: " + numbers.values());
}
}

输出

TreeMap: {One=1, Three=3, Two=2}
/值映射: [One=1, Three=3, Two=2]
: [One, Three, Two]
: [1, 3, 2]

2. 使用 get() 和 getOrDefault()

  • get() - 返回与指定键关联的值。如果未找到键,则返回 null。
  • getOrDefault() - 返回与指定键关联的值。如果未找到键,则返回指定的默认值。

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// 使用 get()
int value1 = numbers.get("Three");
System.out.println("使用 get(): " + value1);

// 使用 getOrDefault()
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("使用 getOrDefault(): " + value2);
}
}

输出

TreeMap: {One=1, Three=3, Two=2}
使用 get(): 3
使用 getOrDefault(): 5

这里,getOrDefault() 方法未找到键 Five。因此,它返回了指定的默认值 5

移除 TreeMap 元素

  • remove(key) - 返回并移除与指定键关联的条目
  • remove(key, value) - 只有当指定的键与指定的值关联时才移除条目,并返回一个布尔值

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// 单参数 remove 方法
int value = numbers.remove("Two");
System.out.println("移除的值: " + value);

// 双参数 remove 方法
boolean result = numbers.remove("Three", 3);
System.out.println("条目 {Three=3} 是否被移除? " + result);

System.out.println("更新后的 TreeMap: " + numbers);
}
}

输出

TreeMap: {One=1, Three=3, Two=2}
移除的值 = 2
条目 {Three=3} 是否被移除? True
更新后的 TreeMap: {One=1}

替换 TreeMap 元素

  • replace(key, value) - 用新的 value 替换由指定 key 映射的值
  • replace(key, old, new) - 只有当旧值已与指定键关联时才用新值替换旧值
  • replaceAll(function) - 用指定 function 的结果替换映射中的每个值

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("原始 TreeMap: " + numbers);

// 使用 replace()
numbers.replace("Second", 22);
numbers.replace("Third", 3, 33);
System.out.println("使用 replace 的 TreeMap: " + numbers);

// 使用 replaceAll()
numbers.replaceAll((key, oldValue) -> oldValue + 2);
System.out.println("使用 replaceAll 的 TreeMap: " + numbers);
}
}

输出

原始 TreeMap: {First=1, Second=2, Third=3}
使用 replace(): {First=1, Second=22, Third=33}
使用 replaceAll(): {First=3, Second=24, Third=35}

在上面的程序中,请注意这条语句

numbers.replaceAll((key, oldValue) -> oldValue + 2);

这里,我们传递了一个 lambda 表达式 作为参数。

replaceAll() 方法访问映射的所有

条目。然后用新值(lambda 表达式返回的值)替换所有元素。

导航方法

由于 TreeMap 类实现了 NavigableMap,它提供了多种方法来遍历 treemap 的元素。

1. 首位和末位方法

  • firstKey() - 返回映射的第一个键
  • firstEntry() - 返回映射中第一个键的键/值映射
  • lastKey() - 返回映射的最后一个键
  • lastEntry() - 返回映射中最后一个键的键/值映射

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);

// 使用 firstKey() 方法
String firstKey = numbers.firstKey();
System.out.println("第一个键: " + firstKey);

// 使用 lastKey() 方法
String lastKey = numbers.lastKey();
System.out.println("最后一个键: " + lastKey);

// 使用 firstEntry() 方法
System.out.println("第一个条目: " + numbers.firstEntry());


// 使用 lastEntry() 方法
System.out.println("最后一个条目: " + numbers.lastEntry());
}
}

输出

TreeMap: {First=1, Second=2, Third=3}
第一个键: First
最后一个键: Third
第一个条目: First=1
最后一个条目: Third=3

2. 天花板、地板、更高和更低方法

  • higherKey() - 返回所有比指定键大的键中最小的键。
  • higherEntry() - 返回与大于指定键的最小键关联的条目。
  • lowerKey() - 返回所有比指定键小的键中最大的键。
  • lowerEntry() - 返回与小于指定键的最大键关联的条目。
  • ceilingKey() - 如果作为参数传递的键在映射中存在,它将返回该键;否则,返回所有大于指定键的键中最小的键。
  • ceilingEntry() - 如果与作为参数传递的键关联的条目在映射中存在,它将返回该条目;否则,返回与大于指定键的最小键关联的条目。
  • floorKey() - 如果作为参数传递的键在映射中存在,它将返回该键;否则,返回所有小于指定键的键中最大的键。
  • floorEntry() - 如果与作为参数传递的键关联的条目在映射中存在,它将返回该条目;否则,返回与小于指定键的最大键关联的条目。 例如,
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 5);
numbers.put("Third", 4);
numbers.put("Fourth", 6);
System.out.println("TreeMap: " + numbers);

// 使用 higher()
System.out.println("使用 higherKey(): " + numbers.higherKey("Fourth"));
System.out.println("使用 higherEntry(): " + numbers.higherEntry("Fourth"));

// 使用 lower()
System.out.println("\n使用 lowerKey(): " + numbers.lowerKey("Fourth"));
System.out.println("使用 lowerEntry(): " + numbers.lowerEntry("Fourth"));

// 使用 ceiling()
System.out.println("\n使用 ceilingKey(): " + numbers.ceilingKey("Fourth"));
System.out.println("使用 ceilingEntry(): " + numbers.ceilingEntry("Fourth"));

// 使用 floor()
System.out.println("\n使用 floorKey(): " + numbers.floorKey("Fourth"));
System.out.println("使用 floorEntry(): " + numbers.floorEntry("Fourth"));


}
}

输出

TreeMap: {First=1, Fourth=6, Second=5, Third=4}
使用 higherKey(): Second
使用 higherEntry(): Second=5

使用 lowerKey(): First
使用 lowerEntry(): First=1

使用 ceilingKey(): Fourth
使用 ceilingEntry(): Fourth=6

使用 floorkey(): Fourth
使用 floorEntry(): Fourth=6

3. pollFirstEntry() 和 pollLastEntry() 方法

  • pollFirstEntry() - 返回并移除映射中第一个键关联的条目
  • pollLastEntry() - 返回并移除映射中最后一个键关联的条目

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);

// 使用 pollFirstEntry() 方法
System.out.println("使用 pollFirstEntry(): " + numbers.pollFirstEntry());

// 使用 pollLastEntry() 方法
System.out.println("使用 pollLastEntry(): " + numbers.pollLastEntry());

System.out.println("更新后的 TreeMap: " + numbers);

}
}

输出

TreeMap: {First=1, Second=2, Third=3}
使用 pollFirstEntry(): First=1
使用 pollLastEntry(): Third=3
更新后的 TreeMap: {Second=2}

4. headMap(), tailMap() 和 subMap() 方法

headMap(key, booleanValue)

headMap() 方法返回在指定 key(作为参数传递)之前的所有键/值对。

booleanValue 参数是可选的。其默认值为 false

如果传递 true 作为 booleanValue,该方法还包括作为参数传递的 key 的键/值对。

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\n使用 headMap() 方法:");
// 使用默认 booleanValue 的 headMap()
System.out.println("不使用 boolean 值: " + numbers.headMap("Fourth"));

// 使用指定 booleanValue 的 headMap()
System.out.println("使用 boolean 值: " + numbers.headMap("Fourth", true));

}
}


输出

TreeMap: {First=1, Fourth=4, Second=2, Third=3}

使用 headMap() 方法:
不使用 boolean: {First=1}
使用 boolean: {First=1, Fourth=4}

tailMap(key, booleanValue)

tailMap() 方法返回一个 treemap 中从指定的 key (作为参数传递)开始的所有键/值对。

booleanValue 是一个可选参数。其默认值为 true

如果作为 booleanValue 传递 false,则该方法不包括指定 key 的键/值对。

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\n使用 tailMap() 方法:");
// 使用默认的 booleanValue 的 tailMap()
System.out.println("不带 boolean 值: " + numbers.tailMap("Second"));

// 使用指定的 booleanValue 的 tailMap()
System.out.println("带 boolean 值: " + numbers.tailMap("Second", false));

}
}

输出

TreeMap: {First=1, Fourth=4, Second=2, Third=3}

使用 tailMap() 方法:
不带 boolean: {Second=2, Third=3}
boolean: {Third=3}

subMap(k1, bV1, k2, bV2)

subMap() 方法返回所有与 k1k2 之间的键相关联的条目,包括 k1 的条目。

bV1bV2 是可选的布尔参数。bV1 的默认值为 truebV2 的默认值为 false

如果作为 bV1 传递 false,则方法返回所有与 k1k2 之间的键相关联的条目,不包括 k1 的条目。

如果作为 bV2 传递 true,则方法返回所有与 k1k2 之间的键相关联的条目,包括 k2 的条目。

例如,

import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\n使用 subMap() 方法:");
// 使用默认的 booleanValue 的 subMap()
System.out.println("不带 boolean 值: " + numbers.subMap("Fourth", "Third"));

// 使用指定的 booleanValue 的 subMap()
System.out.println("带 boolean 值: " + numbers.subMap("Fourth", false, "Third", true));

}
}

输出

TreeMap: {First=1, Fourth=2, Second=2, Third=3}

使用 subMap() 方法:
不带 boolean: {Fourth=4, Second=2}
boolean: {Second=2, Third=3}

TreeMap 的其他方法

方法描述
clone()创建 TreeMap 的一个副本
containsKey()搜索 TreeMap 中指定的键,并返回一个布尔结果
containsValue()搜索 TreeMap 中指定的值,并返回一个布尔结果
size()返回 TreeMap 的大小
clear()TreeMap 中移除所有条目

TreeMap 比较器

在上面的所有例子中,treemap 元素自然排序(升序)。然而,我们也可以自定义键的排序。

为此,我们需要创建基于键在 treemap 中排序的自定义比较器类。例如,

import java.util.TreeMap;
import java.util.Comparator;

class Main {
public static void main(String[] args) {

// 创建一个带有自定义比较器的 treemap
TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator());

numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);
}

// 创建比较器类
public static class CustomComparator implements Comparator<String> {

@Override
public int compare(String number1, String number2) {
int value = number1.compareTo(number2);

// 元素以相反顺序排序
if (value > 0) {
return -1;
}
else if (value < 0) {
return 1;
}
else {
return 0;
}
}
}
}

输出

TreeMap: {Third=3, Second=2, Fourth=4, First=1}

在上面的示例中,我们创建了一个传递 CustomComparator 类作为参数的 treemap。

CustomComparator 类实现了 Comparator 接口。

我们随后重写了 compare() 方法,以便以相反顺序对元素进行排序。

要了解更多信息,请访问 Java Comparator (官方 Java 文档)