【java源码】LinkedHashSet、LinkedHashMap详解

LinkedHashSet底层为LinkedHashMap,故本文主要围绕LinkedHashMap展开

LinkedHashSet 简述

核心成员变量

构造器

1. LinkedHashSet(int initialCapacity, float loadFactor)
2. LinkedHashSet(int initialCapacity)
3. LinkedHashSet()
4. LinkedHashSet(Collection<? extends E> c)

以上函数本质都是调用父类HashSetHashSet(int initialCapacity, float loadFactor, boolean dummy)构造器。

  1. dummy参数只是一个为了与HashSet其他构造器区分而设计的,没有实际作用
  2. HashSet(int initialCapacity, float loadFactor, boolean dummy)的底层是LinkedHashMappublic LinkedHashMap(int initialCapacity, float loadFactor)

成员方法

全部继承自HashSet

LinkedHashMap

核心成员变量

  1. transient LinkedHashMap.Entry<K,V> head,头指针
  2. transient LinkedHashMap.Entry<K,V> tail,尾指针
  3. final boolean accessOrder,默认为false。为trueLinkedHashMap以访问顺序排序,否则以插入顺序排序
  4. Entry<K,V>,继承了父类的内部类Node,仅添加了两个成员变量beforeafter,以实现双向链表。同时,由于继承了next属性,故仍可对table数组上同一位置的链表遍历。
    HashMap.TreeNode->LinkedHashMap.Entry->HashMap.Node->Map.Entry

笔者认为HashMap.TreeNode可以直接继承HashMap.Node,因为在实现中实际并未用到继承得来的Entry<K,V> before, after


//LinkedHashMap
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);
    }
}
//HashMap
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }
    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString() { return key + "=" + value; }
	//重写了hashCode方法
    public final int hashCode() {
        return Objects.hashCode(key) ^ Objects.hashCode(value);
    }

    public final V setValue(V newValue) {
        ...
    }
    public final boolean equals(Object o) {
        ...
    }
}

构造器

  1. LinkedHashMap(int initialCapacity, float loadFactor)
  2. LinkedHashMap(int initialCapacity)
  3. LinkedHashMap()
  4. LinkedHashMap(Map<? extends K, ? extends V> m)
  5. LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder)
    以上构造器本质均为调用父类HashMap对应的构造器。

成员方法

独有方法

  1. linkNodeLast(p),将结点连在原链表末尾
  2. transferLinks(LinkedHashMap.Entry<K,V> src,LinkedHashMap.Entry<K,V> dst),将原链表的该结点替换为新的结点

重写方法

  1. newNode(int hash, K key, V value, Node<K,V> e)
  2. newTreeNode(int hash, K key, V value, Node<K,V> next)
  3. replacementNode(Node<K,V> p, Node<K,V> next)

  4. 重写主要是为了适应新的数据结构,功能逻辑不变

entrySet()、keySet()、values()

功能逻辑与HashMap相同,主要是内部类LinkedHashIteratornextNode方法是按双向链表的链接遍历的。因此和HashMapHashIteratornextNode有点区别。
注意

  1. LinkedEntrySetHashMap类的EntrySet分别继承自AbstractSet类。因此二者是兄弟关系而非子父类关系。
  2. LinkedHashIterator nextNode方法有别于HashIterator的同名方法
    1. HashIteratornextNode每次被调用时若nextnull则均需要在数组中找到下一个非null元素
    2. LinkedHashMap由于有头指针且支持按次序访问,因此能一次访问全部非null节点
public Set<Map.Entry<K,V>> entrySet() {
    Set<Map.Entry<K,V>> es;
    return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}
//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();
    }
    public final boolean contains(Object o) {
        ...
    }
    public final boolean remove(Object o) {
        ...
        }
        return false;
    }
    public final Spliterator<Map.Entry<K,V>> spliterator() {
        ...
    }
    public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
        ...
    }
}
//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;
    }
	//不同于HashMap中HashIterator的nextNode
	//LinkedHashMap由于有头指针且支持按次序访问,因此能一次访问全部节点,中间不会遇到节点为null的情况。
	//而HashIterator的nextNode每次被调用时若next为null则均需要在数组中找到下一个非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;
        return e;
    }

    public final void remove() {
        ...
    }
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值