Java TreeMap与示例

时间:2020-01-09 10:35:04  来源:igfitidea点击:

Java中的TreeMap是Map接口的实现之一。它与其他实现HashMap的不同之处在于,与无序的HashMap不同,TreeMap是Sorted的。

默认情况下,TreeMap根据其键的自然顺序进行排序。如果我们想要不同的排序顺序,则必须在TreeMap构建时提供一个Comparator。

Java TreeMap是基于Red-Black树的Map实现。 TreeMap类扩展AbstractMap并实现NavigableMap,Cloneable和Serializable接口。

TreeMap的功能

本文中讨论的Java TreeMap的某些功能如下:

  • 在TreeMap中,元素按键排序。
  • 在TreeMap中,值可以重复,但是键必须是唯一的。
  • TreeMap不允许使用空键,但可以使用空值。
  • Java中的TreeMap不是线程安全的。
  • TreeMap的所有"集合视图方法"返回的迭代器都是快速失败的。这意味着,如果在创建迭代器之后的任何时候都对结构进行了结构修改,则除了通过迭代器自己的remove方法之外,该迭代器都将以其他方式通过ConcurrentModificationException抛出。

Java TreeMap构造函数

  • TreeMap()使用其键的自然顺序构造一个新的空树形图。

  • TreeMap(Comparator <?super K>比较器)构造一个新的空树图,根据给定的比较器排序。

  • TreeMap(Map <?扩展K ,?扩展V> m)构造一个新树图,该树图包含与给定图相同的映射,并根据其键的自然顺序进行排序。

  • TreeMap(SortedMap <K,?extended V> m)构造一个新的树图,该树图包含与指定的排序图相同的映射,并使用相同的顺序。

Java示例创建TreeMap

让我们看一个创建TreeMap并将元素插入TreeMap的示例。我们将显示这些值以查看排序顺序。

import java.util.Map;
import java.util.TreeMap;

public class TreeMapDemo {
  public static void main(String[] args) {
    Map<Integer, String> studentMap = new TreeMap<Integer, String>();
    studentMap.put(1001, "Amy");
    studentMap.put(1210, "Root");
    studentMap.put(2340, "Frodo");
    studentMap.put(1345, "Chris");
    studentMap.put(1440, "Chris");
    studentMap.put(1345, "Zidane");
    
    for(Map.Entry<Integer, String> entry : studentMap.entrySet()){
      System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
    }
  }
}

输出:

Key is 1001 Value is Amy
Key is 1210 Value is Root
Key is 1345 Value is Zidane
Key is 1440 Value is Chris
Key is 2340 Value is Frodo

从输出中,我们可以看到元素是按键排序的。由于Integer的自然顺序是递增的,因此键是按升序排序的。

键1345插入了两次,因为键必须唯一,这就是为什么相同键的值将被覆盖的原因。

在TreeMap中,不允许使用空键

我们可以尝试通过在TreeMap中添加null作为键来检查TreeMap不允许null作为键。它应该抛出NullPointerExpcetion。

public class TreeMapDemo {
  public static void main(String[] args) {
    Map<Integer, String> studentMap = new TreeMap<Integer, String>();
    studentMap.put(1001, "Amy");
    studentMap.put(1210, "Root");
    studentMap.put(2340, "Frodo");
    studentMap.put(1345, "Chris");
    studentMap.put(1440, "Chris");
    studentMap.put(null, "Zidane");

    for(Map.Entry<Integer, String> entry : studentMap.entrySet()){
      System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
    }
  }
}

输出:

Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.TreeMap.put(TreeMap.java:561)
	at com.theitroad.TreeMapDemo.main(TreeMapDemo.java:15)

更改TreeMap中的排序顺序

如果要更改TreeMap中的排序顺序,则必须提供一个Comparator。在上一个示例中,如果我们希望键按降序排序,则可以按以下步骤进行操作。

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

public class TreeMapDemo {
  public static void main(String[] args) {
    // TreeMap with comparator
    Map<Integer, String> studentMap = new TreeMap<Integer, String>(new KeyComparator());
    studentMap.put(1001, "Amy");
    studentMap.put(1210, "Root");
    studentMap.put(2340, "Frodo");
    studentMap.put(1345, "Chris");
    studentMap.put(1440, "Chris");
    studentMap.put(2134, "Zidane");
    
    for(Map.Entry<Integer, String> entry : studentMap.entrySet()){
      System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
    }
  }
}
// Comparator
class KeyComparator implements Comparator<Integer>{
  @Override
  public int compare(Integer o1, Integer o2) {
    // TODO Auto-generated method stub
    return o2.compareTo(o1);
  }
}

输出:

Key is 2340 Value is Frodo
Key is 2134 Value is Zidane
Key is 1440 Value is Chris
Key is 1345 Value is Chris
Key is 1210 Value is Root
Key is 1001 Value is Amy

TreeMap类中的方法

Java TreeMap类中某些方法的列表。

  • ceilingEntry(K key)返回与大于或者等于给定键的最小键关联的键-值映射关系;如果没有这样的键,则返回null。

  • ceilingKey(K key)返回大于或者等于给定键的最小键;如果没有这样的键,则返回null。

  • clear()从此映射中删除所有映射。

  • containsKey(Object key)如果此映射包含指定键的映射,则返回true。

  • containsValue(Object value)如果此映射将一个或者多个键映射到指定值,则返回true。

  • floorEntry(K key)返回与小于或者等于给定键的最大键关联的键-值映射关系;如果没有这样的键,则返回null。

  • floorKey(K key)返回小于或者等于给定密钥的最大密钥;如果没有这样的密钥,则返回null。

  • get(Object key)返回指定键映射到的值;如果此映射不包含该键的映射,则返回null。

  • keySet()返回此映射中包含的键的Set视图。

  • remove(Object key)从此TreeMap中删除此键的映射(如果存在)。

  • size()返回此映射中的键值映射数。

  • subMap(K fromKey,K toKey)返回此地图部分的视图,其键范围从fromKey(包括)到toKey(不包括)。

  • tailMap(K fromKey)返回此地图的一部分的视图,其键大于或者等于fromKey。

TreeMap实现不同步

Java中的TreeMap不同步,因此不是线程安全的。如果多个线程同时访问TreeMap,并且至少有一个线程在结构上修改了地图,则必须在外部进行同步。我们可以使用Collections.synchronizedSortedMap方法包装TreeMap。

SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));

Java TreeMap迭代器

我们不能直接在Map中使用迭代器。我们将必须获取Map的集合视图,然后对其进行迭代。 TreeMap的集合视图方法返回的迭代器是快速失败的。如果在创建迭代器后的任何时候修改了集合,则除了通过迭代器自己的remove方法以外,都以任何方式修改了该迭代器,该迭代器将抛出ConcurrentModificationException。

迭代TreeMap Java示例

public class TreeMapDemo {
  public static void main(String[] args) {
    // TreeMap with comparator
    Map<Integer, String> studentMap = new TreeMap<Integer, String>();
    studentMap.put(1001, "Amy");
    studentMap.put(1210, "Root");
    studentMap.put(2340, "Frodo");
    studentMap.put(1345, "Chris");
    studentMap.put(1440, "Chris");
    studentMap.put(2134, "Zidane");
        
    // iterating map
    Iterator<Map.Entry<Integer, String>> itr = studentMap.entrySet().iterator();
    while(itr.hasNext()) {
      Map.Entry<Integer, String> entry = itr.next();
      System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
    }
  }
}

输出:

Key is 1001 Value is Amy
Key is 1210 Value is Root
Key is 1345 Value is Chris
Key is 1440 Value is Chris
Key is 2134 Value is Zidane
Key is 2340 Value is Frodo