Java集合框架:了解LinkedHashMap

LinkedHashMap

基于哈希表(数组,链表,红黑树)与双向链表实现的哈希映射

目录

LinkedHashMap继承关系

LinkedHashMap源码解析

LinkedHashMap总结


LinkedHashMap继承关系

LinkedHashMap继承了HashMap抽象类,拥有HashMap的所有操作

LinkedHashMap源码解析

静态 类 Entry<K,V>:

/**
 * 继承自HashMap的节点类
 * 添加了:
 *  记录前一个节点变量before
 *  记录后一个节点变量after
 */
static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

不可变 类LinkedKeySet:

/**
 * 继承自AbstractSet
 */
final class LinkedKeySet extends AbstractSet<K> {
    public final int size()                 { return size; }
    public final void clear()               { LinkedHashMap.this.clear(); }
    public final Iterator<K> iterator() {
        return new LinkedKeyIterator(); // 返回Key的迭代器
    }

    public final boolean contains(Object o) { return containsKey(o); }
    public final boolean remove(Object key) {
        return removeNode(hash(key), key, null, false, true) != null;   // HashMap的removeNode方法
    }

    public final Spliterator<K> spliterator()  {
        return Spliterators.spliterator(this, Spliterator.SIZED |
                                        Spliterator.ORDERED |
                                        Spliterator.DISTINCT);
    }

    public final void forEach(Consumer<? super K> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
            action.accept(e.key);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

不可变 类LinkedValues:


final class LinkedValues extends AbstractCollection<V> {
    public final int size()                 { return size; }
    public final void clear()               { LinkedHashMap.this.clear(); }
    public final Iterator<V> iterator() {
        return new LinkedValueIterator();   // 返回值的迭代器
    }
    public final boolean contains(Object o) { return containsValue(o); }
    public final Spliterator<V> spliterator() {
        return Spliterators.spliterator(this, Spliterator.SIZED |
                                        Spliterator.ORDERED);
    }
    public final void forEach(Consumer<? super V> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
            action.accept(e.value);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

不可变 类LinkedEntrySet:

final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
    public final int size()                 { return size; }
    public final void clear()               { LinkedHashMap.this.clear(); }
    public final Iterator<Map.Entry<K,V>> iterator() {
        return new LinkedEntryIterator();   // 返回Entry的迭代器
    }
    public final boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<?,?> e = (Map.Entry<?,?>) o;
        Object key = e.getKey();
        Node<K,V> candidate = getNode(hash(key), key);  // HashMap的getNode
        return candidate != null && candidate.equals(e);
    }
    public final boolean remove(Object o) {
        if (o instanceof Map.Entry) {
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
            Object key = e.getKey();
            Object value = e.getValue();
            return removeNode(hash(key), key, value, true, true) != null;
        }
        return false;
    }
    public final Spliterator<Map.Entry<K,V>> spliterator() {
        return Spliterators.spliterator(this, Spliterator.SIZED |
                                        Spliterator.ORDERED |
                                        Spliterator.DISTINCT);
    }
    public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
            action.accept(e);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

抽象 类迭代器LinkedHashIterator:

abstract class LinkedHashIterator {
    LinkedHashMap.Entry<K,V> next;      // 下一个元素
    LinkedHashMap.Entry<K,V> current;   // 当前元素
    int expectedModCount;               // 迭代器修改计数器

    LinkedHashIterator() {
        next = head;
        expectedModCount = modCount;    // 迭代器计数 == 集合计数
        current = null;
    }

    public final boolean hasNext() {
        return next != null;
    }

    final LinkedHashMap.Entry<K,V> nextNode() {
        LinkedHashMap.Entry<K,V> e = next;
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        if (e == null)
            throw new NoSuchElementException();
        current = e;
        next = e.after; // next 指向 e 的下一个节点
        return e;
    }

    public final void remove() {
        Node<K,V> p = current;
        if (p == null)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        current = null;
        removeNode(p.hash, p.key, null, false, false);  // 删除当前节点current
        expectedModCount = modCount;
    }
}

final class LinkedKeyIterator extends LinkedHashIterator
implements Iterator<K> {
    public final K next() { return nextNode().getKey(); }
}

final class LinkedValueIterator extends LinkedHashIterator
implements Iterator<V> {
    public final V next() { return nextNode().value; }
}

final class LinkedEntryIterator extends LinkedHashIterator
implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}

LinkedHashMap构造方法:

/**
 * 构造一个具有 指定初始容量 和 负载因子 的空LinkedHashMap
 *
 * @param  initialCapacity the initial capacity
 * @param  loadFactor      the load factor
 * @throws IllegalArgumentException if the initial capacity is negative
 *         or the load factor is nonpositive
 */
public LinkedHashMap(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor);
    accessOrder = false;
}

/**
 * 构造一个具有 指定初始容量 和 默认负载因子=0.75 的空LinkedHashMap
 *
 * @param  initialCapacity the initial capacity
 * @throws IllegalArgumentException if the initial capacity is negative
 */
public LinkedHashMap(int initialCapacity) {
    super(initialCapacity);
    accessOrder = false;
}

/**
 * 构造一个具有 默认初始容量=16 和 默认负载因子=0.75 的空LinkedHashMap
 */
public LinkedHashMap() {
    super();
    accessOrder = false;
}

/**
 * 使用与指定映射相同的映射构造一个按插入顺序排列的LinkedHashMap
 * LinkedHashMap使用默认的负载因子=0.75和足够容纳m的初始容量
 *
 * @param  m the map whose mappings are to be placed in this map
 * @throws NullPointerException if the specified map is null
 */
public LinkedHashMap(Map<? extends K, ? extends V> m) {
    super();
    accessOrder = false;
    putMapEntries(m, false);
}

/**
 * 使用指定的初始容量、负载因子和排序模式构造一个空LinkedHashMap
 *
 * @param  initialCapacity the initial capacity
 * @param  loadFactor      the load factor
 * @param  accessOrder     the ordering mode - {@code true} for
 *         access-order, {@code false} for insertion-order
 * @throws IllegalArgumentException if the initial capacity is negative
 *         or the load factor is nonpositive
 */
public LinkedHashMap(int initialCapacity,
                        float loadFactor,
                        boolean accessOrder) {
    super(initialCapacity, loadFactor);
    this.accessOrder = accessOrder;
}

LinkedHashMap其他方法:

 // 链接在列表的末尾
 private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
    LinkedHashMap.Entry<K,V> last = tail; // 原最后一个节点
    tail = p;
    if (last == null)
        // 最后节点为空, 设置为头节点
        head = p;
    else {
        p.before = last;
        last.after = p;
    }
}

/**
 * 连接两个节点之间的前后指针
 */
private void transferLinks(LinkedHashMap.Entry<K,V> src,
                           LinkedHashMap.Entry<K,V> dst) {
    LinkedHashMap.Entry<K,V> b = dst.before = src.before;
    LinkedHashMap.Entry<K,V> a = dst.after = src.after;
    if (b == null)
        head = dst;
    else
        b.after = dst;
    if (a == null)
        tail = dst;
    else
        a.before = dst;
}

// overrides of HashMap hook methods

/**
 * 重置LinkedHashMap为初始默认状态
 */
void reinitialize() {
    super.reinitialize();
    head = tail = null;
}

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
    LinkedHashMap.Entry<K,V> p =
        new LinkedHashMap.Entry<>(hash, key, value, e);
    linkNodeLast(p);    // 链接到末尾
    return p;
}

Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
    LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
    LinkedHashMap.Entry<K,V> t =
        new LinkedHashMap.Entry<>(q.hash, q.key, q.value, next);
    transferLinks(q, t); // 链接两个节点的前后指针
    return t;
}

/**
 * 新建树节点, 链接到末尾
 */
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
    TreeNode<K,V> p = new TreeNode<>(hash, key, value, next);
    linkNodeLast(p);
    return p;
}

TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
    LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
    TreeNode<K,V> t = new TreeNode<>(q.hash, q.key, q.value, next);
    transferLinks(q, t);
    return t;
}

/**
 * 删除节点e, 处理e节点前后节点的指针
 */
void afterNodeRemoval(Node<K,V> e) {
    LinkedHashMap.Entry<K,V> p =
        (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
    p.before = p.after = null; // 指针置空
    if (b == null)
        head = a;
    else
        b.after = a;
    if (a == null)
        tail = b;
    else
        a.before = b;
}

/**
 * 用于当超出缓存容器大小时移除最老的首节点
 * 但是removeEldestEntry方法恒定返回false, 使得此方法无意义
 * 若要使用需重写removeEldestEntry方法
 */
void afterNodeInsertion(boolean evict) { // possibly remove eldest
    LinkedHashMap.Entry<K,V> first;
    // 删除第一个节点?
    if (evict && (first = head) != null && removeEldestEntry(first)) {
        K key = first.key;
        removeNode(hash(key), key, null, false, true);
    }
}

/**
 * 移动节点到末尾
 */
void afterNodeAccess(Node<K,V> e) {
    LinkedHashMap.Entry<K,V> last;
    if (accessOrder && (last = tail) != e) {
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after; // Node e 转为 Entry p
        p.after = null;
        // 这里将a和b链接
        if (b == null)
            head = a;
        else
            b.after = a;
        if (a != null)
            a.before = b;
        else
            last = b;
        // 将原来的最后一个节点和p链接
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
        tail = p;
        ++modCount;
    }
}

void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
    for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
        s.writeObject(e.key);
        s.writeObject(e.value);
    }
}

/**
 * 如果此映射将一个或多个键映射到指定的值
 * 则返回true
 *
 * @param value value whose presence in this map is to be tested
 * @return {@code true} if this map maps one or more keys to the
 *         specified value
 */
public boolean containsValue(Object value) {
    for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
        V v = e.value;
        if (v == value || (value != null && value.equals(v)))
            return true;
    }
    return false;
}

/**
 * 若LinkedHashMap包含一个从key到value的映射
 * 使得key==null ? k == null : key.equals(k)
 * 则该方法返回 v, 否则返回 null
 */
public V get(Object key) {
    Node<K,V> e;
    if ((e = getNode(hash(key), key)) == null)
        return null;
    if (accessOrder)
        afterNodeAccess(e);
    return e.value;
}

/**
 * 获取key对应映射的值, 若没有则返回defaultValue
 */
public V getOrDefault(Object key, V defaultValue) {
    Node<K,V> e;
    if ((e = getNode(hash(key), key)) == null)
        return defaultValue;
    if (accessOrder)
        afterNodeAccess(e);
    return e.value;
}

/**
 * 清空map的元素
 */
public void clear() {
    super.clear();
    head = tail = null;
}

/**
 * 如果映射应该删除最老的条目, 则返回true
 */
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
    return false;
}

/**
 * 返回包含在此映射中的键的Set视图
 * 对map的更改也会反应在Set视图中, 反之亦然
 * 支持remove, removeAll, retainAll, clear操作
 * 不支持add和addAll操作
 * 
 * Spliterator提供了比HashMap更快的顺序性能
 * 但是并行性能较差
 * 
 * @return a set view of the keys contained in this map
 */
public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new LinkedKeySet();
        keySet = ks;
    }
    return ks;
}

/**
 * 返回包含在此映射中的值的Collection视图
 * 对map的更改也会反应在Collection视图中, 反之亦然
 * 支持remove, removeAll, retainAll, clear操作
 * 不支持add和addAll操作
 * 
 * Spliterator提供了比HashMap更快的顺序性能
 * 但是并行性能较差
 * 
 * @return a view of the values contained in this map
 */
public Collection<V> values() {
    Collection<V> vs = values;
    if (vs == null) {
        vs = new LinkedValues();
        values = vs;
    }
    return vs;
}

/**
 * 返回包含在这个映射中的Set视图
 * 对map的更改也会反应在Set视图中, 反之亦然
 * 支持remove, removeAll, retainAll, clear操作
 * 不支持add和addAll操作
 * 
 * Spliterator提供了比HashMap更快的顺序性能
 * 但是并行性能较差
 *
 * @return a set view of the mappings contained in this map
 */
public Set<Map.Entry<K,V>> entrySet() {
    Set<Map.Entry<K,V>> es;
    return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}

// Map overrides

public void forEach(BiConsumer<? super K, ? super V> action) {
    if (action == null)
        throw new NullPointerException();
    int mc = modCount;
    for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
        action.accept(e.key, e.value);
    if (modCount != mc)
        throw new ConcurrentModificationException();
}

public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
    if (function == null)
        throw new NullPointerException();
    int mc = modCount;
    for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
        e.value = function.apply(e.key, e.value);
    if (modCount != mc)
        throw new ConcurrentModificationException();
}

LinkedHashMap总结

LinkedHashMap允许使用null键和null值。

LinkedHashMap是线程不安全的,无同步策略。

LinkedHashMap相比于HashMap是有序的。

LinkedHashMap不保证映射的顺序,有可预知的迭代顺序(插入顺序或者是访问顺序)。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值