集合专区---第8集(TreeMap)

1 TreeMap的本质是什么?
二叉树 

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
NavigableMap 翻译之后叫做: 可导航的Map

//比较器,因为TreeMap是有序的,通过comparator接口我们可以对TreeMap的内部排序进行精密的控制
private final Comparator<? super K> comparator;  
//TreeMap红-黑节点,为TreeMap的内部类  
private transient Entry<K,V> root = null;  
//容器大小  
private transient int size = 0;
//TreeMap修改次数  
private transient int modCount;

2 排序方式

可以自定义排序方式,或者默认按照插入属性排序

3 HashMap,LinkedHashMap,TreeMap 什么时候用哪种?

LinkedHashMap继承自HashMap。如果只需要存储功能,使用HashMap与LinkedHashMap是一种更好的选择;如果还需要保证统计性能或者需要对Key按照一定规则进行排序,那么使用treemap是一种更好的选择。LinkedHashMap还额外保证了Map的遍历顺序可以与put顺序一致,解决了HashMap本身无序的问题。

HashMap和LinkedHashMap做的比较不好,此时我们可以使用TreeMap。TreeMap的key按照自然顺序进行排序或者根据创建映射时提供的Comparator接口进行排序。TreeMap为增、删、改、查这些操作提供了log(N)的时间开销,从存储角度而言,这比HashMap与LinkedHashMap的o(1)时间负责度要差些;但是在统计性能上,TreeMap同时可以保证log(N)的时间开销,这又比HashMap和LinkedHashMap的o(N)时间复杂度好不少。

4 特点

它是线程不安全的,但是可以通过下面方式设置成线程安全

Map m = Collections.synchronizedSortedMap(new TreeMap(…));

5 排序的不同,可以根据构造方法的不同去实现排序的不同

6 key不可以为null,但是如果比较器对null做处理的话就可以

7 如果没有设置自定义的比较器,那我们将获取key的类型所在的比较器,例如String 类型继承了Comparable,那么我们就默认使用String类的比较器。

8 put方法逻辑

  • 首先判断是不是第一个元素,如果是则作为根节点
  • 判断是否有自定义比较器,否则判断key是否为null,否则就用类自带的比较器去存储数据
public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}

9 get方法逻辑

  • 首先判断输入的key通过比较器是否小于二叉树中最小的元素,或者大于最大的,如果是,返回null
  • 然后接着去获取元素,判断是否是自定义的比较器,否则判断key是否为null,否则根据key类型获取自带的比较器去获取数据
public V get(Object key) {
    Entry<K,V> p = getEntry(key);
    return (p==null ? null : p.value);
}
final Entry<K,V> getEntry(Object key) {
    // Offload comparator-based version for sake of performance
    if (comparator != null)
        return getEntryUsingComparator(key);
    if (key == null)
        throw new NullPointerException();
    @SuppressWarnings("unchecked")
        Comparable<? super K> k = (Comparable<? super K>) key;
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = k.compareTo(p.key);
        if (cmp < 0)
            p = p.left;
        else if (cmp > 0)
            p = p.right;
        else
            return p;
    }
    return null;
}

总结:

  1. 实现方式 
    HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
    (1)HashMap(): 构建一个空的哈希映像 
    (2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射 
    (3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像 
    (4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像 
    TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。 
    (1)TreeMap():构建一个空的映像树 
    (2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素 
    (3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序 
    (4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序
  2. 用途 
    HashMap:适用于在Map中插入、删除和定位元素。 
    TreeMap:适用于按自然顺序或自定义顺序遍历键(key)。 
    HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap.

3 视频中讲错的地方
 

public V put(K key, V value) //这个方法会执行
public final V put(K key, V value) //调用put方法的时候该方法不会被调用,如有问题请发评论告知
public V get(Object key) { //这个方法会执行
    Entry<K,V> p = getEntry(key);
    return (p==null ? null : p.value);
}
public final V get(Object key) {//调用get方法的时候该方法不会被调用,如有问题请发评论告知
    return !inRange(key) ? null :  m.get(key);
}

猜你喜欢

转载自blog.csdn.net/weixin_39405857/article/details/89705870
今日推荐