记录treeMap

140 阅读2分钟

概述

TreeMap 是 Java 集合框架中的一种有序映射(键值对)实现,它基于红黑树数据结构来维护元素的有序性。

关键代码

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

// 内部节点类,继承自红黑树的节点基类
private static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left;
    Entry<K,V> right;
    Entry<K,V> parent;
    boolean color = BLACK;
}

// 红黑树根节点
private transient Entry<K,V> root;

// 比较器
private final Comparator<? super K> comparator;

// ...

// 插入节点并进行平衡操作
private Entry<K,V> putVal(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;
    // ...
    
    // 进行红黑树的平衡操作
    fixAfterInsertion(x);
    return null;
}

// 红黑树的插入平衡操作
private void fixAfterInsertion(Entry<K,V> x) {
    x.color = RED;
    while (x != null && x != root && x.parent.color == RED) {
        // ...
    }
    root.color = BLACK;
}

// ...

// 获取指定键的节点
final Entry<K,V> getEntry(Object key) {
    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;
}

// ...
}

TreeMap 设计思想和应用场景

设计思想:

  1. 有序性维护: TreeMap 通过使用红黑树这种自平衡二叉搜索树的数据结构,可以保持元素的有序性。红黑树的平衡性能够确保在插入、删除元素时,树的高度不会过高,从而保证了操作的时间复杂度稳定在 O(log N)。
  2. 二叉搜索树: TreeMap 的底层数据结构是一棵二叉搜索树(BST)。这种树结构使得在查找、插入和删除元素时能够迅速定位到目标节点,提高了操作的效率。
  3. 平衡性维护: 红黑树作为一种自平衡的二叉搜索树,在插入和删除操作时能够通过旋转和重新着色来保持树的平衡,避免了出现极端不平衡的情况,从而保证了较稳定的性能。

应用场景:

  1. 有序数据存储: 当需要存储有序的键值对数据时,TreeMap 是一个很好的选择。它能够保持元素的有序性,使得元素可以按照键的顺序进行迭代和访问。
  2. 范围查询: TreeMap 支持范围查询操作,可以很方便地获取某个范围内的键值对。例如,找到大于等于某个键的最小键值对,或者找到小于等于某个键的最大键值对。
  3. 按照优先级处理: 在某些场景中,需要按照优先级或权重来处理元素。TreeMap 可以根据键的比较来实现这种有序的处理方式。
  4. LRU 缓存: TreeMap 可以用来实现 LRU(最近最少使用)缓存,通过在每次访问元素时将其移动到树的末尾,从而实现缓存的自动淘汰。