treemap 了解

Tue, Feb 16, 2021 2-minute read

treeMap 一直出现在各种算法中,可是我每次都很难记得清它的用法,所以来一个笔记,让自己了解的更清楚点

lowerKey()方法用于返回严格小于给定键(作为参数传递)的最大键。用简单的话来说,此方法用于查找作为参数传递的元素之后的下一个最大元素。

 // create an empty TreeMap 
        TreeMap<Integer, String> 
            numMap = new TreeMap<Integer, String>(); 
  
        // Insert the values 
        numMap.put(6, "Six"); 
        numMap.put(1, "One"); 
        numMap.put(5, "Five"); 
        numMap.put(3, "Three"); 
        numMap.put(8, "Eight"); 
        numMap.put(10, "Ten"); 
  
        // Print the Values of TreeMap 
        System.out.println("TreeMap: " + numMap.toString()); 
  
        // Get the greatest key mapping of the Map 
  
        // As here 9 is not available it returns 8 
        // because 9 is strictly less than 11, present 
        System.out.print("Lower Key Entry of Element 9 is: "); 
        System.out.println(numMap.lowerKey(9)); 
  
        // Though, 3 is available in the Map 
        // it returns 1 because this method returns 
        // strictly less than key according to the specified key 
        System.out.print("Lower Key Entry of Element 3 is: "); 
        System.out.println(numMap.lowerKey(3)); 

Lower Key Entry of Element 9 is: 8

Lower Key Entry of Element 3 is: 1

floorKey()方法用于从参数中返回小于或等于给定键的最大键。

 // create an empty TreeMap 
        TreeMap<Integer, String> numMap = new TreeMap<Integer, String>(); 
  
        // Insert the values 
        numMap.put(6, "Six"); 
        numMap.put(1, "One"); 
        numMap.put(5, "Five"); 
        numMap.put(3, "Three"); 
        numMap.put(8, "Eight"); 
        numMap.put(10, "Ten"); 
  
        // Print the Values of TreeMap 
        System.out.println("TreeMap: " + numMap.toString()); 
  
        // Get the greatest key mapping of the Map 
  
        // As here 11 is not available it returns 10 
        // because ten is less than 11 
        System.out.print("Floor Entry of Element 11 is: "); 
        System.out.println(numMap.floorKey(11)); 
  
        // This will give null 
        System.out.print("Floor Entry of Element 0 is: "); 
        System.out.println(numMap.floorKey(0)); 
    } 

Floor Entry of Element 11 is: 10

Floor Entry of Element 0 is: null

HashMap

同时遍历 key 和 value 时,keySet 与 entrySet 方法的性能差异取决于 key 的具体情况,

如复杂度(复杂对象)、离散度、冲突率等。换言之,取决于 HashMap 查找 value 的开销。

entrySet 一次性取出所有 key 和 value 的操作是有性能开销的,当这个损失小于 HashMap 查找 value 的开销时,entrySet 的性能优势就会体现出来。

当 key 是最简单的数值字符串时,keySet 可能反而会更高效,耗时比 entrySet 少 10%。

总体来说还是推荐使用 entrySet。因为当 key 很简单时,其性能或许会略低于 keySet,但却是可控的;而随着 key 的复杂化,entrySet 的优势将会明显体现出来。当然,我们可以根据实际情况进行选择

只遍历 key 时,keySet 方法更为合适,因为 entrySet 将无用的 value 也给取出来了,浪费了性能和空间。在上述测试结果中,keySet 比 entrySet 方法耗时少 23%。

只遍历 value 时,使用 vlaues 方法是最佳选择,entrySet 会略好于 keySet 方法。

在不同的遍历写法中,推荐使用如下写法,其效率略高一些:

for (String key : map.keySet()) {

    value = map.get(key);

}
for (Entry<String, String> entry: map.entrySet()) {

    key = entry.getKey();

    value = entry.getValue();

}
for (String value : map.values()) {

}

TreeMap

同时遍历 key 和 value 时,与 HashMap 不同,entrySet 的性能远远高于 keySet。这是由 TreeMap 的查询效率决定的,

也就是说,TreeMap 查找 value 的开销较大,明显高于 entrySet 一次性取出所有 key 和 value 的开销。因此,遍历 TreeMap 时强烈推荐使用 entrySet 方法。

只遍历 key 时,keySet 方法更为合适,因为 entrySet 将无用的 value 也给取出来了,浪费了性能和空间。在上述测试结果中,keySet 比 entrySet 方法耗时少 24%。

只遍历 value 时,使用 vlaues 方法是最佳选择,entrySet 也明显优于 keySet 方法。