原文: https://www.programiz.com/java-programming/treemap

在本教程中,我们将借助示例学习 Java TreeMap类及其操作。

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

它实现了NavigableMap接口

Java TreeMap - 图1


创建一个TreeMap

为了创建一个TreeMap,我们必须首先导入java.util.TreeMap包。 导入包后,可以使用以下方法在 Java 中创建TreeMap

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

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

但是,我们可以使用Comparator接口自定义元素的排序。 我们将在本教程的后面部分中学习它。

这里,

  • key - 用于关联映射中每个元素(值)的唯一标识符
  • value - 映射中与按键相关联的元素

TreeMap的方法

TreeMap类提供了各种方法,可让我们在映射上执行操作。


将元素插入TreeMap

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

例如,

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. // Creating TreeMap of even numbers
  5. TreeMap<String, Integer> evenNumbers = new TreeMap<>();
  6. // Using put()
  7. evenNumbers.put("Two", 2);
  8. evenNumbers.put("Four", 4);
  9. // Using putIfAbsent()
  10. evenNumbers.putIfAbsent("Six", 6);
  11. System.out.println("TreeMap of even numbers: " + evenNumbers);
  12. //Creating TreeMap of numbers
  13. TreeMap<String, Integer> numbers = new TreeMap<>();
  14. numbers.put("One", 1);
  15. // Using putAll()
  16. numbers.putAll(evenNumbers);
  17. System.out.println("TreeMap of numbers: " + numbers);
  18. }
  19. }

输出

  1. TreeMap of even numbers: {Four=4, Six=6, Two=2}
  2. TreeMap of numbers: {Four=4, One=1, Six=6, Two=2}

访问TreeMap元素

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

  • entrySet() - 返回树形图的所有键/值映射(条目)的集合
  • keySet() - 返回树形图的所有键的集合
  • values() - 返回树形图的所有图的集合

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("One", 1);
  6. numbers.put("Two", 2);
  7. numbers.put("Three", 3);
  8. System.out.println("TreeMap: " + numbers);
  9. // Using entrySet()
  10. System.out.println("Key/Value mappings: " + numbers.entrySet());
  11. // Using keySet()
  12. System.out.println("Keys: " + numbers.keySet());
  13. // Using values()
  14. System.out.println("Values: " + numbers.values());
  15. }
  16. }

输出

  1. TreeMap: {One=1, Three=3, Two=2}
  2. Key/Value mappings: [One=1, Three=3, Two=2]
  3. Keys: [One, Three, Two]
  4. Values: [1, 3, 2]

2.使用get()getOrDefault()

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("One", 1);
  6. numbers.put("Two", 2);
  7. numbers.put("Three", 3);
  8. System.out.println("TreeMap: " + numbers);
  9. // Using get()
  10. int value1 = numbers.get("Three");
  11. System.out.println("Using get(): " + value1);
  12. // Using getOrDefault()
  13. int value2 = numbers.getOrDefault("Five", 5);
  14. System.out.println("Using getOrDefault(): " + value2);
  15. }
  16. }

输出

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

在此,getOrDefault()方法找不到键Five。 因此,它返回指定的默认值5


删除TreeMap元素

  • remove(key) - 返回并从TreeMap中删除与指定键关联的条目
  • remove(key, value) - 仅在指定键与指定值相关联并返回布尔值时,才从映射中删除条目

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("One", 1);
  6. numbers.put("Two", 2);
  7. numbers.put("Three", 3);
  8. System.out.println("TreeMap: " + numbers);
  9. // remove method with single parameter
  10. int value = numbers.remove("Two");
  11. System.out.println("Removed value: " + value);
  12. // remove method with two parameters
  13. boolean result = numbers.remove("Three", 3);
  14. System.out.println("Is the entry {Three=3} removed? " + result);
  15. System.out.println("Updated TreeMap: " + numbers);
  16. }
  17. }

输出

  1. TreeMap: {One=1, Three=3, Two=2}
  2. Removed value = 2
  3. Is the entry {Three=3} removed? True
  4. Updated TreeMap: {One=1}

替换TreeMap元素

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. System.out.println("Original TreeMap: " + numbers);
  9. // Using replace()
  10. numbers.replace("Second", 22);
  11. numbers.replace("Third", 3, 33);
  12. System.out.println("TreeMap using replace: " + numbers);
  13. // Using replaceAll()
  14. numbers.replaceAll((key, oldValue) -> oldValue + 2);
  15. System.out.println("TreeMap using replaceAll: " + numbers);
  16. }
  17. }

输出

  1. Original TreeMap: {First=1, Second=2, Third=3}
  2. TreeMap using replace(): {First=1, Second=22, Third=33}
  3. TreeMap using replaceAll(): {First=3, Second=24, Third=35}

在上述程序中,声明

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

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

replaceAll()方法访问映射的所有条目。 然后,它将所有元素替换为新值(从 lambda 表达式返回)。


用于导航的方法

由于TreeMap类实现了NavigableMap,因此它提供了多种方法来浏览树图的元素。

1.首先和最后的方法

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. System.out.println("TreeMap: " + numbers);
  9. // Using the firstKey() method
  10. String firstKey = numbers.firstKey();
  11. System.out.println("First Key: " + firstKey);
  12. // Using the lastKey() method
  13. String lastKey = numbers.lastKey();
  14. System.out.println("Last Key: " + lastKey);
  15. // Using firstEntry() method
  16. System.out.println("First Entry: " + numbers.firstEntry());
  17. // Using the lastEntry() method
  18. System.out.println("Last Entry: " + numbers.lastEntry());
  19. }
  20. }

输出

  1. TreeMap: {First=1, Second=2, Third=3}
  2. First Key: First
  3. Last Key: Third
  4. First Entry: First=1
  5. Last Entry: Third=3

2.上限,下限,上下限方法

  • upperKey() - 返回大于指定键的那些键中的最低键。
  • upperEntry() - 返回与所有大于指定键的键中最低的键相关的条目。
  • lowerKey() - 返回所有小于指定键的最大键。
  • lowerEntry() - 返回与所有小于指定键的键中最大的键关联的条目。
  • ceilingKey() - 返回大于指定键的那些键中的最低键。 如果映射中存在作为参数传递的键,则它将返回该键。
  • ceilingEntry() - 返回与大于指定键的那些键中最低的键相关联的条目。 如果映射中存在与传递给自变量的键关联的条目,则它返回与该键关联的条目。
  • floorKey() - 返回小于指定键的那些键中最大的键。 如果存在作为参数传递的键,它将返回该键。
  • floorEntry() - 返回与小于指定键的那些键中最大的键关联的条目。 如果存在作为参数传递的键,它将返回该键。

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 5);
  7. numbers.put("Third", 4);
  8. numbers.put("Fourth", 6);
  9. System.out.println("TreeMap: " + numbers);
  10. // Using higher()
  11. System.out.println("Using higherKey(): " + numbers.higherKey("Fourth"));
  12. System.out.println("Using higherEntry(): " + numbers.higherEntry("Fourth"));
  13. // Using lower()
  14. System.out.println("\nUsing lowerKey(): " + numbers.lowerKey("Fourth"));
  15. System.out.println("Using lowerEntry(): " + numbers.lowerEntry("Fourth"));
  16. // Using ceiling()
  17. System.out.println("\nUsing ceilingKey(): " + numbers.ceilingKey("Fourth"));
  18. System.out.println("Using ceilingEntry(): " + numbers.ceilingEntry("Fourth"));
  19. // Using floor()
  20. System.out.println("\nUsing floorKey(): " + numbers.floorKey("Fourth"));
  21. System.out.println("Using floorEntry(): " + numbers.floorEntry("Fourth"));
  22. }
  23. }

输出

  1. TreeMap: {First=1, Fourth=6, Second=5, Third=4}
  2. Using higherKey(): Second
  3. Using higherEntry(): Second=5
  4. Using lowerKey(): First
  5. Using lowerEntry(): First=1
  6. Using ceilingKey(): Fourth
  7. Using ceilingEntry(): Fourth=6
  8. Using floorkey(): Fourth
  9. Using floorEntry(): Fourth=6

3. pollFirstEntry()pollLastEntry()方法

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. System.out.println("TreeMap: " + numbers);
  9. //Using the pollFirstEntry() method
  10. System.out.println("Using pollFirstEntry(): " + numbers.pollFirstEntry());
  11. // Using the pollLastEntry() method
  12. System.out.println("Using pollLastEntry(): " + numbers.pollLastEntry());
  13. System.out.println("Updated TreeMap: " + numbers);
  14. }
  15. }

输出

  1. TreeMap: {First=1, Second=2, Third=3}
  2. Using pollFirstEntry(): First=1
  3. Using pollLastEntry(): Third=3
  4. Updated TreeMap: {Second=2}

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

headMap(key, booleanValue)

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

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

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. numbers.put("Fourth", 4);
  9. System.out.println("TreeMap: " + numbers);
  10. System.out.println("\nUsing headMap() Method:");
  11. // Using headMap() with default booleanValue
  12. System.out.println("Without boolean value: " + numbers.headMap("Fourth"));
  13. // Using headMap() with specified booleanValue
  14. System.out.println("With boolean value: " + numbers.headMap("Fourth", true));
  15. }
  16. }

输出

  1. TreeMap: {First=1, Fourth=4, Second=2, Third=3}
  2. Using headMap() Method:
  3. Without boolean value: {First=1}
  4. With boolean value: {First=1, Fourth=4}

tailMap(key, booleanValue)

tailMap()方法返回从指定的key(作为参数传递)开始的树形图的所有键/值对。

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

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. numbers.put("Fourth", 4);
  9. System.out.println("TreeMap: " + numbers);
  10. System.out.println("\nUsing tailMap() Method:");
  11. // Using tailMap() with default booleanValue
  12. System.out.println("Without boolean value: " + numbers.tailMap("Second"));
  13. // Using tailMap() with specified booleanValue
  14. System.out.println("With boolean value: " + numbers.tailMap("Second", false));
  15. }
  16. }

输出

  1. TreeMap: {First=1, Fourth=4, Second=2, Third=3}
  2. Using tailMap() Method:
  3. Without boolean value: {Second=2, Third=3}
  4. With boolean value: {Third=3}

subMap(k1, bV1, k2, bV2)

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

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

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

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

例如:

  1. import java.util.TreeMap;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeMap<String, Integer> numbers = new TreeMap<>();
  5. numbers.put("First", 1);
  6. numbers.put("Second", 2);
  7. numbers.put("Third", 3);
  8. numbers.put("Fourth", 4);
  9. System.out.println("TreeMap: " + numbers);
  10. System.out.println("\nUsing subMap() Method:");
  11. // Using subMap() with default booleanValue
  12. System.out.println("Without boolean value: " + numbers.subMap("Fourth", "Third"));
  13. // Using subMap() with specified booleanValue
  14. System.out.println("With boolean value: " + numbers.subMap("Fourth", false, "Third", true));
  15. }
  16. }

输出

  1. TreeMap: {First=1, Fourth=2, Second=2, Third=3}
  2. Using subMap() Method:
  3. Without boolean value: {Fourth=4, Second=2}
  4. With boolean value: {Second=2, Third=3}

TreeMap的其他方法

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

TreeMap比较器

在以上所有示例中,treemap元素都自然排序(以升序排列)。 但是,我们也可以自定义键的顺序。

为此,我们需要基于对树图中的键进行排序的方式来创建自己的比较器类。 例如,

  1. import java.util.TreeMap;
  2. import java.util.Comparator;
  3. class Main {
  4. public static void main(String[] args) {
  5. // Creating a treemap with a customized comparator
  6. TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator());
  7. numbers.put("First", 1);
  8. numbers.put("Second", 2);
  9. numbers.put("Third", 3);
  10. numbers.put("Fourth", 4);
  11. System.out.println("TreeMap: " + numbers);
  12. }
  13. // Creating a comparator class
  14. public static class CustomComparator implements Comparator<String> {
  15. @Override
  16. public int compare(String number1, String number2) {
  17. int value = number1.compareTo(number2);
  18. // elements are sorted in reverse order
  19. if (value > 0) {
  20. return -1;
  21. }
  22. else if (value < 0) {
  23. return 1;
  24. }
  25. else {
  26. return 0;
  27. }
  28. }
  29. }
  30. }

输出

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

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

CustomComparator类实现Comparator接口。

然后,我们覆盖compare()方法以按相反顺序对元素进行排序。

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