java有序的Map-LinkedHashMap

HashMap中的keySet

public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

final class KeySet extends AbstractSet<K> {
    public final int size()                 { return size; }
    public final void clear()               { HashMap.this.clear(); }
    public final Iterator<K> iterator()     { return new KeyIterator(); }
    public final boolean contains(Object o) { return containsKey(o); }
    public final boolean remove(Object key) {
        return removeNode(hash(key), key, null, false, true) != null;
    }
    public final Spliterator<K> spliterator() {
        return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer<? super K> action) {
        Node<K,V>[] tab;
        if (action == null)
            throw new NullPointerException();
        if (size > 0 && (tab = table) != null) {
            int mc = modCount;
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K,V> e = tab[i]; e != null; e = e.next)
                    action.accept(e.key);
            }
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }
}

HashMap在获取keySet的时候就是创建了一个Set集合,但是该实体并没有保存实际的信息,而是所有的实现都是HashMap的实现,这样做的好处是不用在添加或者删除的时候去操作这个集合。

HashMap的这个keySet是懒加载的,只有在调用的时候才去建立,减少内存的浪费。

LinkedHashMap中的keySet

两种有序的方式

  • 根据插入进行排序
  • 根据读取进行排序
public class Main {
    public static void main(String[] args) {
    	// 插入排序
        LinkedHashMap<Integer, Integer> linkedHashMap = new LinkedHashMap<>(8, 0.75F, false);
        linkedHashMap.put(1,2);
        linkedHashMap.put(2,2);
        linkedHashMap.get(1);
        System.out.println(linkedHashMap.keySet());

		// 根据读取及进行排序
        LinkedHashMap<Integer, Integer> linkedHashMapAccess = new LinkedHashMap<>(8, 0.75F, true);
        linkedHashMapAccess.put(1,2);
        linkedHashMapAccess.put(2,2);
        linkedHashMapAccess.get(1);
        System.out.println(linkedHashMapAccess.keySet());
    }
}

实现

实现载体

其中的实现就是依赖于链表的有序结构,再插入删除或者获取数组的时候,添加或者才做节点的位置即可。

    /**
     * The head (eldest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> head;

    /**
     * The tail (youngest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> tail;

实现过程

修改节点的位置

LinkedHashMap继承自HashMap,所有在实体插入元素的时候,实际是去调用HashMap的方法,在HashMap中有三个方法值得注意。

    // 添加链表使用
    void afterNodeAccess(Node<K,V> p) { }
    // 是否删除最早的节点
    void afterNodeInsertion(boolean evict) { }
    // 删除节点使用
    void afterNodeRemoval(Node<K,V> p) { }

此处是HashMap为我们提供的方法,在所有进行插入,删除,获取的时候都进行了调用,但是HashMap中没有具体实现,如果我们想要自定义一个Map,有一个排序规则,只需要重写这里的方法即可,不用做大面积的修改。一个好的设计是可用于扩展的。

三个方法的具体实在在这里不进行展开,大家可以到LinkedHash源码中查看,就是维护一个链表。

获取keySet

forEach中从头节点开始比比遍历列表。

 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();
        }
        public final boolean contains(Object o) { return containsKey(o); }
        public final boolean remove(Object key) {
            return removeNode(hash(key), key, null, false, true) != null;
        }
        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();
        }
    }

JAVA集合目录

java集合目录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值