List集合源码分析


java集合主要包含两种类型Collection(集合)、Map(图),Collection存储一个元素集合,Map存储键值对,Collection下面分为List、Set、Queue,虚线框的都是接口或者抽象类不可直接使用,实线框中才能直接使用,常用的集合有ArrayList、HashSet、LinkedList、LinkedHashSet、HashMap、LinkedHashMap

==================================================================
ArrayList源码分析
contains方法在ArrayList中实现,源码如下

public boolean contains(Object o) {
    return indexOf(o) >= 0;
}


public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

个人理解:contains方法首先判断被比较对象是否为空,如果为空的话则调用Iterator迭代器逐一对比集合中有的元素,如果集合存在元素为空返回true,如果被比较对象不可空同样调用Iterator迭代器逐一对比,相同则返回true,对比方法为equals。
被比较对象equals使用默认Object原生方法比较的是两个元素的内存地址,如果被比较对象有重写equals方法则比较内容。

add方法在ArrayList中实现,源码如下

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

//ArrayList扩容判断
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

//ArrayList扩容算法
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

个人理解:ArrayList集合内部维护的是一个Object数组,add方法首先判断数组大小是否需要扩容,
扩容具体逻辑是是否使用默认构造方法,如果是则和默认数组大小10比较返回最大值,如果不是默认构造方法构造直接返回当前需要的容器大小。具体扩容逻辑在grow方法中,自动扩容1.5倍,如果还不能满足则扩容到Inter.MAX_VALUE-8大小。
ArrayList最大容量为Inter.MAX_VALUE。

toArray方法在Arraylist中实现,源码如下

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

个人理解:System.arraycopy方法是ArrayList中使用非常频繁的方法,是Native静态方法,是一个非常高效的数组拷贝方法。arraycopy第一个参数表示源数组,第二个参数表示源数组要复制的起始位置,第三个参数表示目标数组,第四个参数为目标数组起始位置,第五个参数表示复制源数组的长度。

Iterator迭代器源码如下

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    Itr() {}

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

个人理解:Iterator迭代器在ArrayList中的实现为内部类方式,迭代器操作为不安全线程操作,为了防止出现集合数据不一致,迭起器在每个方法执行前加了checkForComodification验证,判断改变次数是否一致,是否是在迭代器内部进行的数据操作。

LinkedList源码分析
Linked继承了List,LinkedList是一个双向链表,它是由每个node节点组成,每个node节点具有三个属性,分别是item、next、prev,item是当前节点内容,next是当前节点指向的下一个节点地址,prev是上个节点地址。它可以用来实现队列、栈等数据模型。

push方法源码如下

private void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null, e, f);
    first = newNode;
    if (f == null)
        last = newNode;
    else
        f.prev = newNode;
    size++;
    modCount++;
}

add方法源码如下

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

pop方法源码如下

//从头部开始删除
public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);
}

//从尾部开始删除
public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return unlinkLast(l);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值