Arraylist

1.继承关系

在这里插入图片描述
从图中可以看出Arraylist继承AbstractList类(AbstractList继承了AbstractCollection类,同时实现了list类),同时实现了Serializable、List(继承了collection接口,collection接口继承了Iterable接口)、Cloneable、RandomAccess(快速随机访问)

2.属性

在这里插入图片描述
重要的属性

  1. Object[] elementData 对象数组
  2. DEFAULT_CAPACITY 数组默认大小10
  3. size数组大小
  4. modCount修改次数 在AbstractList中定义

3.构造方法

在这里插入图片描述

ArrayList()

	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

在注释上面可以看到Constructs an empty list with an initial capacity of ten.构造一个初始为10的空数组,但是实际上是将定义的常量空数组赋值给elementData,如果使用无参的构造函数实际上是在add方法中添加的长度。

ArrayList(Collection<? extends E> c)

	public ArrayList(Collection<? extends E> c) {
		//collection转array
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // defend against c.toArray (incorrectly) not returning Object[]
            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
            if (elementData.getClass() != Object[].class)
            	//判断集合是否是Object类型,如果不是则转换成object类型
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

根据集合来创建arraylist,最终保存的是object的数组或者一个空数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
主要是为了解决https://bugs.openjdk.java.net/browse/JDK-6260652这个bug

ArrayList(int initialCapacity)

	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);
        }
    }

根据传入的值初始化数组大小

常用方法

add

add方法向外提供两种,第一种是add(E e)默认往最后一个位置新增,第二种add(int index, E element),向指定位置新增

add(E e)

 public boolean add(E e) {
 		//每操作一次modCount++,主要是因为Arraylist不是线程安全类
        modCount++;
        add(e, elementData, size);
        return true;
    }
//重载的私有的add
private void add(E e, Object[] elementData, int s) {
		//插入的位置等于数组长度就需要扩容
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

add(int index, E element)

public void add(int index, E element) {
		//判断插入的时候是否越界,因为arraylist不是线程安全的,多线程的时候可能存在已经插入的情况
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        //考虑扩容
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        //将原来index到末尾的值全部copy移到后面一位
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }

扩容grow方法

private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

 public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // assert oldLength >= 0
        // assert minGrowth > 0

        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        //越界判断
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

可以看出扩容是从原数组大小1.5倍和最小期望值大小中取最大,同时还需考虑越界问题

remove

向外提供的删除方法有两种,一个是remove(int index),一个是remove(Object o)

	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;
    }

	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++)
	                    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;
        if ((newSize = size - 1) > i)
            System.arraycopy(es, i + 1, es, i, newSize - i);
        es[size = newSize] = null;
    }

可以看到在remove(int index)当中会跟add(Object o , int index)一样先检查index是否越界,因为arraylist是非线程安全的,在多线程中可能存在同时新增或者删除的情况,所以需要先检查是否越界。remove(Object o )中可以看出删除的是第一个对象,同时也可以看出在新增的时候是可以新增null的。fastRemove主要是将数组的index+1到末尾copy到index到末尾。

iterator()

因为Arraylist实现了Iterator接口,所以也可以用迭代器访问

//返回了一个内部迭代器对象
public Iterator<E> iterator() {
        return new Itr();
}

Itr

在这里插入图片描述
属性:

  1. cursor 下一个要返回的元素的索引,默认赋值0
  2. lastRet 最后一个返回元素的索引,-1表示没有值
  3. expectedModCount 期待的修改数

方法

  1. hasNext()
	public boolean hasNext() {
			//下一个值是否是数组大小,如果是就不能继续迭代
            return cursor != size;
    }

2.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();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
		final void checkForComodification() {
			//表示迭代期间集合被修改需要抛出异常
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

3.remove()

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();
            }
        }

从迭代器代码中也可以看出arraylist非线程安全,考虑线程安全的话可以使用Collections.synchronizedList

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值