TreeMap 学习

TreeMap 简介

TreeMap 是一个有序的key-value 集合,内部通过红黑树实现;

TreeMap 继承了AbstractMap类,所以它是一个key-value集合;

TreeMap 实现了NavigableMap接口,而NavigableMap接口继承了SortedMap接口,所以它是一个有序的集合;

TreeMap 实现了Cloneable接口,所以它能被克隆;

TreeMap 实现了Serializable接口,所以它支持序列化;

TreeMap 的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable

 

TreeMap 的属性

private final Comparator<? super K> comparator; 集合排序的排序器,如果创建map时没有指定排序器,那么集合的key必须实现Comparable接口,并重写compareTo方法;

private transient Entry<K,V> root = null; 集合存储数据的数据结构,实现是红黑树,类Entry<K,V> 有key,value,left,right,parent和color6个属性;

private transient int size = 0; 集合中元素的个数;

private transient int modCount = 0; 集合修改的次数;

 

TreeMap 构造方法

TreeMap 提供了4种构造方法,一个无参数和3个需要参数;

// 无参数构造器默认排序器为null;
public TreeMap() {
    comparator = null;
}

// 创建一个自定义排序器的有序key-value集合;		
public TreeMap(Comparator<? super K> comparator) {
    this.comparator = comparator;
}	
	
public TreeMap(Map<? extends K, ? extends V> m) {
    comparator = null;
}

public TreeMap(SortedMap<K, ? extends V> m) {
    comparator = m.comparator();
    try {
        buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
    } catch (java.io.IOException cannotHappen) {
    } catch (ClassNotFoundException cannotHappen) {
    }
}

节点Entry的实现

K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;

TreeMap 主要方法

1、判断是否包含键为key的键值对
public boolean containsKey(Object key) {
   return getEntry(key) != null;
}	
	
2、判断是否包含值为value的键值对
public boolean containsValue(Object value) {
   for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
       if (valEquals(value, e.value))
          return true;
   return false;
}		
    getFirstEntry() 为获取第一个节点(键值对),既最左边的节点;
    successor(e) 获取当前节点的下一个节点;

3、获取键为key的value值
public V get(Object key) {
   Entry<K,V> p = getEntry(key);
   return (p==null ? null : p.value);
}	
	
4、查找键为key的节点
    final Entry<K,V> getEntry(Object key) {
        if (comparator != null)
            return getEntryUsingComparator(key);
        if (key == null)
            throw new NullPointerException();
        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;
    }	
    首先判断有没有自定义的排序器,如果有采用排序器的比较大小的方法比较key与当前节点的key的大小,小于当前节点的key,查找左子树,大于当前节点的key,查找右子树,相等则返回当前节点;如果没有自定义排序器,则采用key对象重写Comparable接口的compareTo方法比较key与当前节点的key的大小关系;

5、插入一个键值对
    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;
        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();
            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;
    }		
(1)、判断根节点是否为null,若果为null,说明是个空集合,创建根节点;
(2)、判断是否存在自定义的比较器,若存在,使用比较器比较key与节点可以的大小关系,否在使用key默认的比较方法(非基本数据类型通过实现接口Comparable的compareTo);
(3)、判断key与当前节点key的大小关系,若比当前节点key小,则查找当前节点的左子树;若比当前节点key大,则查找当前节点的右子树;若相等,则替换当前节点的value值,并返回当前的节点的旧值。
(4)、直到当前节点的子树为空时,此子树的位置为要插入新节点的位置,则在此位置添加新的节点,添加新节点后树不再是红黑树,通过fixAfterInsertion方法重新调整树的结构,使其变成一个红黑树。

6、删除键为key的节点
    public V remove(Object key) {
        Entry<K,V> p = getEntry(key);
        if (p == null)
            return null;
        V oldValue = p.value;
        deleteEntry(p);
        return oldValue;
    }		

7、删除某个节点
    private void deleteEntry(Entry<K,V> p) {
        modCount++;
        size--;
        if (p.left != null && p.right != null) {
            Entry<K,V> s = successor(p);
            p.key = s.key;
            p.value = s.value;
            p = s;
        }
        Entry<K,V> replacement = (p.left != null ? p.left : p.right);

        if (replacement != null) {
            replacement.parent = p.parent;
            if (p.parent == null)
                root = replacement;
            else if (p == p.parent.left)
                p.parent.left  = replacement;
            else
                p.parent.right = replacement;

            p.left = p.right = p.parent = null;

            if (p.color == BLACK)
                fixAfterDeletion(replacement);
        } else if (p.parent == null) {
            root = null;
        } else {
            if (p.color == BLACK)
                fixAfterDeletion(p);

            if (p.parent != null) {
                if (p == p.parent.left)
                    p.parent.left = null;
                else if (p == p.parent.right)
                    p.parent.right = null;
                p.parent = null;
            }
        }
    }

8、获取第一个key或最后一个key
    public K firstKey() {
        return key(getFirstEntry());
    }

    public K lastKey() {
        return key(getLastEntry());
    }

9、克隆一个map
    public Object clone() {
        TreeMap<?,?> clone;
        try {
            clone = (TreeMap<?,?>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }

        clone.root = null;
        clone.size = 0;
        clone.modCount = 0;
        clone.entrySet = null;
        clone.navigableKeySet = null;
        clone.descendingMap = null;

        try {
            clone.buildFromSorted(size, entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }

        return clone;
    }

10、获取第一个键值对和最后一个键值对
    public Map.Entry<K,V> firstEntry() {
        return exportEntry(getFirstEntry());
    }

    public Map.Entry<K,V> lastEntry() {
        return exportEntry(getLastEntry());
    }

11、poll第一个键值对和最后一个键值对
    public Map.Entry<K,V> pollFirstEntry() {
        Entry<K,V> p = getFirstEntry();
        Map.Entry<K,V> result = exportEntry(p);
        if (p != null)
            deleteEntry(p);
        return result;
    }

    public Map.Entry<K,V> pollLastEntry() {
        Entry<K,V> p = getLastEntry();
        Map.Entry<K,V> result = exportEntry(p);
        if (p != null)
            deleteEntry(p);
        return result;
    }

12、如果map集合中存在键值对的key==key,则返回此键值对;如果不存在,在返回比key第一大的键值对
    public Map.Entry<K,V> ceilingEntry(K key) {
        return exportEntry(getCeilingEntry(key));
    }

    public K ceilingKey(K key) {
        return keyOrNull(getCeilingEntry(key));
    }

    final Entry<K,V> getCeilingEntry(K key) {
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = compare(key, p.key);
            if (cmp < 0) {
                if (p.left != null)
                    p = p.left;
                else
                    return p;
            } else if (cmp > 0) {
                if (p.right != null) {
                    p = p.right;
                } else {
                    Entry<K,V> parent = p.parent;
                    Entry<K,V> ch = p;
                    while (parent != null && ch == parent.right) {
                        ch = parent;
                        parent = parent.parent;
                    }
                    return parent;
                }
            } else
                return p;
        }
        return null;
    }

13、如果map集合中存在键值对的key==key,则返回此键值对;如果不存在,在返回比key第一小的键值对
    public Map.Entry<K,V> floorEntry(K key) {
        return exportEntry(getFloorEntry(key));
    }

    public K floorKey(K key) {
        return keyOrNull(getFloorEntry(key));
    }
14、获取比key第一小的键值对
    public Map.Entry<K,V> lowerEntry(K key) {
        return exportEntry(getLowerEntry(key));
    }

    public K lowerKey(K key) {
        return keyOrNull(getLowerEntry(key));
    }
15、获取比key第一大的键值对
    public Map.Entry<K,V> higherEntry(K key) {
        return exportEntry(getHigherEntry(key));
    }

    public K higherKey(K key) {
        return keyOrNull(getHigherEntry(key));
    }
16、返回key集合
    public Set<K> keySet() {
        return navigableKeySet();
    }
    返回有序key集合
    public NavigableSet<K> navigableKeySet() {
        KeySet<K> nks = navigableKeySet;
        return (nks != null) ? nks : (navigableKeySet = new KeySet<>(this));
    }
    返回递减有序的key集合
    public NavigableSet<K> descendingKeySet() {
        return descendingMap().navigableKeySet();
    }
17、返回从fromKey(包括)到tokey(不包括)的键值对
    public SortedMap<K,V> subMap(K fromKey, K toKey) {
        return subMap(fromKey, true, toKey, false);
    }
    返回从第一个到key(不包括)的键值对
    public SortedMap<K,V> headMap(K toKey) {
        return headMap(toKey, false);
    }
    返回从key(包括)以后的键值对
    public SortedMap<K,V> tailMap(K fromKey) {
        return tailMap(fromKey, true);
    }

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值