ArrayList LinkedList源码解析(5)

/**
*Itr 实现了Iterator接口,是AbstractList中的一个内部类。
*/
private class Itr implements Iterator<E> {
    //当前迭代器指向的数组中元素的下一个元素的位置
    int cursor = 0;

int lastRet = -1;

int expectedModCount = modCount;
    //每次调用hasNext方法时,判断当前指向的数组中的位置和数组大小是否相等,若不等则返回true(说明还有值),若相等则返回false(说明已经迭代到了数组的末尾了,没有元素了)
    public boolean hasNext() {
            return cursor != size();
    }
    //调用next方法是,先调用checkForComodification()方法,判断是否有其他线程对集合大小做出了有影响的动作;
    //然后调用get方法获取相应位置的元素,若获取不到,则抛出IndexOutOfBoundsException异常,在捕获到该异常后,调用checkForComodification()方法,
    //检测modcount若== expectedModCount(没有其他线程对集合大小做出了有影响的操作),则抛出NoSuchElementException,若modcount != expectedModCount,则抛出ConcurrentModificationException
    public E next() {
            checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
    }

public void remove() {
        if (lastRet == -1)
        throw new IllegalStateException();
            checkForComodification();

try {
        AbstractList.this.remove(lastRet);
        if (lastRet < cursor)
            cursor--;
        lastRet = -1;
        expectedModCount = modCount;
        } catch (IndexOutOfBoundsException e) {
        throw new ConcurrentModificationException();
        }
    }
    //若modCount和期望的expectedModCount不相等,说明在迭代过程中,有其他的线程对集合大小产生了影响的动作(新增、删除),此时抛出异常ConcurrentModificationException
    final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
}

我们在看一个方法trimToSize

/**
*将elementData数组的容量 缩小为该集合实际包含的元素数量
*/
public void trimToSize() {
    modCount++;
    int oldCapacity = elementData.length;
    if (size < oldCapacity) {
            elementData = Arrays.copyOf(elementData, size);
    }
}

使用ArrayList的注意事项:

1.ArrayList是基于数组的方式实现的,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。
2.ArrayList在插入元素时,可能会进行数组的扩容,但是在删除元素时却不会减小数组的容量,如果希望减小数组的容量,可使用trimToSize方法,在查找元素要遍历数组时,对非null元素使用equals方法,对null元素使用==。
3.扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当 容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍加1,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容 量),而后用Arrays.copyof()方法将元素拷贝到新的数组。从中可以看出,当容量不够时,每次增加元素,都要将原来的元 素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList
4.ArrayList不是线程安全的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a28bd8cda7fd42444934c8d7ef084553.html