ArrayList、LinkedList、LinkedHashMap源码分析

来源:互联网 发布:闪电网络测速工具 编辑:程序博客网 时间:2024/06/05 07:46

本文是看ArrayList、LinkedList、LinkedHashMap源码的一个小结

ArrayList

abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
ArrayList是基于数组实现的,相对于数组,它支持自动扩容。

ArrayList非线程安全,因此也通过modCount来校验。
rivate class SimpleListIterator implements Iterator<E> {        int pos = -1;        int expectedModCount;        int lastPosition = -1;        SimpleListIterator() {            expectedModCount = modCount;        }        public boolean hasNext() {            return pos + 1 < size();        }        public E next() {            if (expectedModCount == modCount) {                try {                    E result = get(pos + 1);                    lastPosition = ++pos;                    return result;                } catch (IndexOutOfBoundsException e) {                    throw new NoSuchElementException();                }            }            throw new ConcurrentModificationException();        }        public void remove() {            if (this.lastPosition == -1) {                throw new IllegalStateException();            }            if (expectedModCount != modCount) {                throw new ConcurrentModificationException();            }            try {                AbstractList.this.remove(lastPosition);            } catch (IndexOutOfBoundsException e) {                throw new ConcurrentModificationException();            }            expectedModCount = modCount;            if (pos == lastPosition) {                pos--;            }            lastPosition = -1;        }    }


数据结构

  /**     * The number of elements in this list.     */    int size;    /**     * The elements in this list, followed by nulls.     */    transient Object[] array;
数据结构相当简单,当前元素数量size,和一个数组。

自动扩容

ArrayList基本上和数组一样,看一下怎么自动扩容的:

if (s < a.length) {            System.arraycopy(a, index, a, index + 1, s - index);        } else {            // assert s == a.length;            Object[] newArray = new Object[newCapacity(s)];            System.arraycopy(a, 0, newArray, 0, index);            System.arraycopy(a, index, newArray, index + 1, s - index);            array = a = newArray;        }
容量不够时,创建了一个新的数组替代原来的array。

扩容逻辑如下:
private static int newCapacity(int currentCapacity) {        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);        return currentCapacity + increment;    }
 private static final int MIN_CAPACITY_INCREMENT = 12;
最小容量增量12, 当前容量小于6时,增量会最小增量;否则,增量为当前容量的一半,即容量增加二分之一。



LinkedList

LinkedList是双向队列, 实现了Deque接口。
class LinkedList<E> extends AbstractSequentialList<E> implements        List<E>, Deque<E>, Queue<E>, Cloneable, Serializable 

和普通链表不同的是,他实现了List接口,支持下标访问,但是实际上也是遍历:
 public E get(int location) {        if (location >= 0 && location < size) {            Link<E> link = voidLink;            if (location < (size / 2)) {                for (int i = 0; i <= location; i++) {                    link = link.next;                }            } else {                for (int i = size; i > location; i--) {                    link = link.previous;                }            }            return link.data;        }        throw new IndexOutOfBoundsException();    }
由于它实现了Deque接口,因此它也可以是个不严格的栈(控制只从一头进出)。

节点结构

  private static final class Link<ET> {        ET data;        Link<ET> previous, next;        Link(ET o, Link<ET> p, Link<ET> n) {            data = o;            previous = p;            next = n;        }    }

支持null值

 public boolean add(E object) {        return addLastImpl(object);    }    private boolean addLastImpl(E object) {        Link<E> oldLast = voidLink.previous;        Link<E> newLink = new Link<E>(object, oldLast, voidLink);        voidLink.previous = newLink;        oldLast.next = newLink;        size++;        modCount++;        return true;    }
add()方法并没有对null值做特殊处理,比如不支持null值的Hashtable会抛出异常。
因此LinkedList支持null值。


LinkedHashMap

LinkedHashMap继承了HashMap,在HashMap的基础上把HashMap的Entry串成了双向队列。
其节点在HashMap的Entry的基础上加上了前、后指针
static class LinkedEntry<K, V> extends HashMapEntry<K, V> {        LinkedEntry<K, V> nxt;        LinkedEntry<K, V> prv;        /** Create the header entry */        LinkedEntry() {            super(null, null, 0, null);            nxt = prv = this;        }        /** Create a normal entry */        LinkedEntry(K key, V value, int hash, HashMapEntry<K, V> next,                    LinkedEntry<K, V> nxt, LinkedEntry<K, V> prv) {            super(key, value, hash, next);            this.nxt = nxt;            this.prv = prv;        }    }
简单的说,LinkedHashMap就是HashMap和LinkedList的合体。

accessOrder和LRU算法

private final boolean accessOrder;


accessOrder,字面意思访问顺序

 if (accessOrder)    makeTail((LinkedEntry<K, V>) e);
 private void makeTail(LinkedEntry<K, V> e) {        // Unlink e        e.prv.nxt = e.nxt;        e.nxt.prv = e.prv;        // Relink e as tail        LinkedEntry<K, V> header = this.header;        LinkedEntry<K, V> oldTail = header.prv;        e.nxt = header;        e.prv = oldTail;        oldTail.nxt = header.prv = e;        modCount++;    }

当accessOrder为false的时候,什么都不做,和原先的一模一样
为ture时,调用makeTail()把当前访问的节点挪到了链表的最后面。

以下代码的输出值为"[3=3, 4=4, 1=1, 2=2]"
    Map<String, Integer> map = new LinkedHashMap<String, Integer>(16,0.75f,true);        map.put("1", 1);        map.put("2", 2);        map.put("3", 3);        map.put("4", 4);        map.get("1");        map.get("2");        System.out.print(map.entrySet());



原创粉丝点击