ArrayList源码分析(jdk12)

1. 成员变量

//默认初始容量
private static final int DEFAULT_CAPACITY = 10;
//共享空实例对象,用这个表示数组为空
private static final Object[] EMPTY_ELEMENTDATA = {};
//共享空实例对象,用这个表示该ArrayList对象是调用默认构造方法创建数组容器
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//数组容器,用于存储数据
transient Object[] elementData;
//容器大小
private int size;
//容器最大大小
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

2. 构造方法

public ArrayList() { 
		//默认构造,DEFAULTCAPACITY_EMPTY_ELEMENTDATA就是个共享的空数组,所以我们用默认构造创建ArrayList时是空的。
		//只有这种方式创建的ArrayList,elementData等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

public ArrayList(int initialCapacity) {
		// 如果以带初始化大小的方式创建,初始数组是有长度的
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
}

public ArrayList(Collection<? extends E> c) {
		//以带初始化内容方式创建
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
        	//判断elementData的类型,如果不为Object[].class才会赋值,如果为Object[].class表示上面toArray方法执行错误了。需要利用这个方法赋值
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 如果传入数组为空的话,和第二种构造方法传入0是一样的
            this.elementData = EMPTY_ELEMENTDATA;
        }
}

  1. add方法
//直接添加一个数据
public boolean add(E e) {
        modCount++;
        //调用了add(e, elementData, size)
        add(e, elementData, size);
        return true;
}
//指定位置添加一个数据
public void add(int index, E element) {
		//下标检查
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
}
    
private void add(E e, Object[] elementData, int s) {
		//如果添加的位置等于当前容器长度,容器扩容,一般为1.5倍
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
}
  1. grow扩容
private Object[] grow() {
	//这里代码上理解扩容1格,其实不一定
    return grow(size + 1);
}

private Object[] grow(int minCapacity) {
		//将容器扩容指定大小
        return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}

private int newCapacity(int minCapacity) {
		//旧容器大小
        int oldCapacity = elementData.length;
        //新容器大小为旧容器的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果新容器的大小小于需求大小,一般发生在第一次添加数据时
        if (newCapacity - minCapacity <= 0) {
        	//如果是以默认构造方法创建的
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // minCapacity<0表示溢出了
                throw new OutOfMemoryError();
            return minCapacity;
        }
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
    }

  1. remove方法
//删除指定对象
public boolean remove(Object o) {
        final Object[] es = elementData;
        final int size = this.size;
        int i = 0;
        //跳出循环还能这样用啊
        found: {
            if (o == null) {
                for (; i < size; i++)
                    if (es[i] == null)
                        break found;
            } else {
                for (; i < size; i++)
                	//这里需要注意的一点,arrayList,remove(Object o)方法删除的是值相同的元素,且只能删除第一个
                    if (o.equals(es[i]))
                        break found;
            }
            return false;
        }
        fastRemove(es, i);
        return true;
}

private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        //fastRemove方法其实只是将该元素后面的元素全部进一位,最后一位置为null,同时size-1;
        if ((newSize = size - 1) > i)
            System.arraycopy(es, i + 1, es, i, newSize - i);
        es[size = newSize] = null;
}

//删除指定下标,这个挺简单的。
public E remove(int index) {
		//检查下标是否越界
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

5. 迭代器

//常见的获取迭代器的方法
public Iterator<E> iterator() {
     //返回了一个内部类
     return new Itr();
}

//迭代器内部类,实现了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;

        // prevent creating a synthetic constructor
        Itr() {}

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

        @SuppressWarnings("unchecked")
        //next方法其实是就是返回数组的当前下标对象
        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();
            //每次next游标都会+1
            cursor = i + 1;
            //每次next都会将lastRet赋值
            return (E) elementData[lastRet = i];
        }
		//之所以迭代器可以正确在遍历中删除元素,就是因为它删除的不是自己的元素,下标不像for循环每次都会自增,而是始终保持在最后一个。。。我们for循环相当于自己给自己做手术,迭代器相当于医生给自己做手术。
        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
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i < size) {
                final Object[] es = elementData;
                if (i >= es.length)
                    throw new ConcurrentModificationException();
                for (; i < size && modCount == expectedModCount; i++)
                    action.accept(elementAt(es, i));
                // update once at end to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }
		//这个方法是用来判断数组有没有在其他地方被修改了,modCount是数组的修改次数,expectedModCount是迭代器保存的数组修改次数,这两个如果不一样说明数组在其他地方修改了,就会报错
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值