Java之ArrayList

  1. ArrayList
    1.1 ArrayList简介
    ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。
    ArrayList继承了AbstractList,实现了 List, RandomAccess, Cloneable, java.io.Serializable接口,线性表的顺序存储,插入删除元素时间复杂度为O(n),求表长和增加元素,取第i元素的为O(1)。
    ArrayList 继承了AbstractList,实现了List,是一个数组队列,提供了添加、删除、遍历等功能.
    ArrayList 实现了RandomAccess 接口, RandomAccess 是一个标志接口,表明实现这个这个接口的 List 集合是支持快速随机访问的。
    ArrayList 实现了Cloneable 接口,即覆盖了函数 clone(),能被克隆。
    ArrayList 实现java.io.Serializable 接口,所以说ArrayList支持序列化,
    ArrayList 中的操作不是线程安全的。
    1.2 ArrayList源码

    package java.util;
    
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    import java.util.function.UnaryOperator;
    
    
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
    	//序列化
        private static final long serialVersionUID = 8683452581122892189L;
    	//默认初始大小
        private static final int DEFAULT_CAPACITY = 10;
    	// 空数组(用于空实例) 
        private static final Object[] EMPTY_ELEMENTDATA = {};
    	//用于默认大小空实例的共享空数组实例。
    	//把它从EMPTY_ELEMENTDATA数组中区分出来,以知道在添加第一个元素时容量需要增加多少。
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    	//保存ArrayList数据的数组
        transient Object[] elementData;
    	//包含的元素个数
        private int size;
    	/**
    	* 带初始容量参数的构造函数。(用户自己指定容量)
    	*/
        public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {
            	//创建initialCapacity大小的数组
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
            	//创建空数组
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
            }
        }
    	/**
    	*默认构造函数,DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为0.初始化为10,也就是说初始是空数
    	 组,当添加第一个元素的时候数组容量才变成10 
    	*/
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    
    	/**
    	* 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
    	*/
        public ArrayList(Collection<? extends E> c) {
        	//toArray()集合转换为数组
            elementData = c.toArray();
            //指定集合的元素个数不为0
            if ((size = elementData.length) != 0) {
    			//c.toArray()可能返回的不是Object类型的数组所以加上下面的语句用于判断
    			//用到了反射的getClass
                if (elementData.getClass() != Object[].class)
                	//copyOf返回的是一个新的数组对象
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
                // 用空数组替代
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }
    
    	/**
    	* 修改这个ArrayList实例的容量是列表的当前大小。 应用程序可以使用此操作来最小化 ArrayList实	
    	例的存储。
    	 */
        public void trimToSize() {
            modCount++;
            if (size < elementData.length) {
                elementData = (size == 0)
                        ? EMPTY_ELEMENTDATA
                        : Arrays.copyOf(elementData, size);
            }
        }
    
    	/**
    	 *ArrayList的扩容机制。
    	 *ArrayList的扩容机制提高了性能,如果每次只扩充一个。频繁的插入会导致频繁的拷贝,
    	  降低性能,而ArrayList的扩容机制避免了这种情况。
    	 *@param minCapacity 所需的最小容量
    	*/
        public void ensureCapacity(int minCapacity) {
            int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 
            ? 0 
            :DEFAULT_CAPACITY;
    
            if (minCapacity > minExpand) {
                ensureExplicitCapacity(minCapacity);
            }
        }
    	/**
    	 *得到最小的扩容量
    	*/
        private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            	//默认的容量与传入的参数取较大值
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            ensureExplicitCapacity(minCapacity);
        }
    	/**
    	 *判断是否需要扩容
    	*/
        private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
            if (minCapacity - elementData.length > 0)
            	//扩容方法
                grow(minCapacity);
        }
    
    	/**
    	* 要分配的最大数组大小 
    	*/
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
    	/**
    	* ArrayList扩容的核心方法。
    	*/
        private void grow(int minCapacity) {
    		//oldCapacity是旧容量
            int oldCapacity = elementData.length;
            //位运算速度大大快于整除运算 右移一位相当于/2的一次方 结果为扩容1.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            //检查新容量是否大于所需要的最小容量,如果小于则容量为最小容量
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            //检查是否容量是否大于最大容量,如果大于则调用hugeCapacity()来比较minCapacity和MAX_ARRAY_SIZE,若 minCapacity>MAX_ARRAY_SIZE 则容量为MAX_ARRAY_SIZE  否则为minCapacity
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
    		
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    	/**
    	* 比较minCapacity和MAX_ARRAY_SIZE
    	*/
        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0)
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE) ?
                    Integer.MAX_VALUE :
                    MAX_ARRAY_SIZE;
        }
    	/**
    	* 返回列表元素个数
    	*/
        public int size() {
            return size;
        }
    
        /**
    	* 列表中不包含元素返回TRUE
    	*/
        public boolean isEmpty() {
            return size == 0;
        }
        
    	/**
    	* 如果列表包含指定的元素,则返回true。
    	*/
        public boolean contains(Object o) {
        	//indexOf()方法:返回此列表中指定元素的首次出现的索引,如果此列表不包含此元素,则 为-1
            return indexOf(o) >= 0;
        }
        
    	/**
    	*返回此列表中指定元素的首次出现的索引,如果此列表不包含此元素,则为-1 
    	*/
        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;
        }
    
        /**
        * 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
        */
        public int lastIndexOf(Object o) {
            if (o == null) {
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    
        /**
        * 返回此ArrayList实例的浅拷贝。(元素本身不被复制)
        */
        public Object clone() {
            try {
                ArrayList<?> v = (ArrayList<?>) super.clone();
                //Arrays.copyOf功能是实现数组的复制,返回复制后的数组。参数是被复制的数组和复制的长度
                //复制后重置指向了旧数组地址
                v.elementData = Arrays.copyOf(elementData, size);
                v.modCount = 0;
                return v;
            } catch (CloneNotSupportedException e) {
                // this shouldn't happen, since we are Cloneable
                throw new InternalError(e);
            }
        }
    
        /**
        * 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
        */
        public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }
    
    	/** 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素);
    	*返回的数组的运行时类型是指定数组的运行时类型。 如果列表适合指定的数组,则返回其中。 
    	*否则,将为指定数组的运行时类型和此列表的大小分配一个新数组。
    	*如果列表适用于指定的数组,其余空间(即数组的列表数量多于此元素),则紧跟在集合结束后的数组中的元素设置为null 。 
    	*(这仅在调用者知道列表不包含任何空元素的情况下才能确定列表的长度。) 
    	*/
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            if (a.length < size)
                // 新建一个运行时类型的数组,但是ArrayList数组的内容
                return (T[]) Arrays.copyOf(elementData, size, a.getClass());
            //调用System提供的arraycopy()方法实现数组之间的复制
            System.arraycopy(elementData, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }
    
        // Positional Access Operations
    
        @SuppressWarnings("unchecked")
        E elementData(int index) {
            return (E) elementData[index];
        }
    
        /**
         * 返回此列表中指定位置的元素。
         */
        public E get(int index) {
            rangeCheck(index);
    
            return elementData(index);
        }
    
        /**
        * 用指定的元素替换此列表中指定位置的元素。 
        **/
        public E set(int index, E element) {
        	//对index进行界限检查
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            //返回原来在这个位置的元素
            return oldValue;
        }
    
        /**
        * 将指定的元素追加到此列表的末尾。
        */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            //ArrayList添加元素的实质就相当于为数组赋值
            elementData[size++] = e;
            return true;
        }
    
        /**
         * 在此列表中的指定位置插入指定的元素。
         */
        public void add(int index, E element) {
        	//对index进行界限检查
            rangeCheckForAdd(index);
    		//保证capacity足够大
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            ///将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
            System.arraycopy(elementData, index, elementData, index + 1,
                    size - index);
            elementData[index] = element;
            size++;
        }
    
        /**
         * 删除该列表中指定位置的元素。 将任何后续元素移动到左侧(从其索引中减去一个元素)。
         */
        public E remove(int index) {
            rangeCheck(index);
    
            modCount++;
            E oldValue = elementData(index);
    
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                        numMoved);
            elementData[--size] = null; // clear to let GC do its work
    		//从列表中删除的元素
            return oldValue;
        }
    
        /**
         * 从列表中删除指定元素的第一个出现(如果存在)。如果列表不包含该元素,则它不会更改。
         * 返回true,如果此列表包含指定的元素
         */
        public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            return false;
        }
    
        /*
         * Private remove method that skips bounds checking and does not
         * return the value removed.
         */
        private void fastRemove(int index) {
            modCount++;
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                        numMoved);
            elementData[--size] = null; // clear to let GC do its work
        }
    
        /**
         * 从列表中删除所有元素。
         */
        public void clear() {
            modCount++;
    
            //把数组中所有的元素的值设为null
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }
    
        /**
         * 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
         */
        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
        }
    
        /**
         * 将指定集合中的所有元素插入到此列表中,从指定的位置开始。
         */
        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
    
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
    
            int numMoved = size - index;
            if (numMoved > 0)
                System.arraycopy(elementData, index, elementData, index + numNew,
                        numMoved);
    
            System.arraycopy(a, 0, elementData, index, numNew);
            size += numNew;
            return numNew != 0;
        }
    
        /**
         * 从此列表中删除所有索引为fromIndex (含)和toIndex之间的元素
         * 将任何后续元素移动到左侧(减少其索引)。
         */
        protected void removeRange(int fromIndex, int toIndex) {
            modCount++;
            int numMoved = size - toIndex;
            System.arraycopy(elementData, toIndex, elementData, fromIndex,
                    numMoved);
    
            // clear to let GC do its work
            int newSize = size - (toIndex-fromIndex);
            for (int i = newSize; i < size; i++) {
                elementData[i] = null;
            }
            size = newSize;
        }
    
        /**
         * 检查给定的索引是否在范围内。
         */
        private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
        /**
         * add和addAll使用的rangeCheck的一个版本
         */
        private void rangeCheckForAdd(int index) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
        /**
         * 返回IndexOutOfBoundsException细节信息
         */
        private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+size;
        }
    
        /**
         * 从此列表中删除指定集合中包含的所有元素。
         */
        public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            //如果此列表被修改则返回true
            return batchRemove(c, false);
        }
    
        /**
         * 仅保留此列表中包含在指定集合中的元素。
         * 换句话说,从此列表中删除其中不包含在指定集合中的所有元素。
         */
        public boolean retainAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, true);
        }
    	
        /**
         * 从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
         * 指定的索引表示初始调用将返回的第一个元素为next。初始调用previous将返回指定索引减1的 元素。
         * 返回的列表迭代器是fail-fast。
         */
        public ListIterator<E> listIterator(int index) {
            if (index < 0 || index > size)
                throw new IndexOutOfBoundsException("Index: "+index);
            return new ListItr(index);
        }
    
        /**
         * 返回列表中的列表迭代器(按适当的顺序)
         * 返回的列表迭代器是fail-fast 。
         */
        public ListIterator<E> listIterator() {
            return new ListItr(0);
        }
    
        /**
         * 以正确的顺序返回该列表中的元素的迭代器。
         * 返回的迭代器是fail-fast。
         */
        public Iterator<E> iterator() {
            return new Itr();
        }
    
        /**
         * 截取fromIndex至toIndex的列表(包含fromIndex的元素)
         */
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    
    	/**
         * 列表排序方法
         */
        @Override
        @SuppressWarnings("unchecked")
        public void sort(Comparator<? super E> c) {
            final int expectedModCount = modCount;
            Arrays.sort((E[]) elementData, 0, size, c);
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    }
    

    1.3 内部类

    (1).private class Itr implements Iterator<E>
    (2).private class ListItr extends Itr implements ListIterator<E>
    (3).private class SubList extends AbstractList<E> implements RandomAccess
    (4).static final class ArrayListSpliterator<E> implements Spliterator<E>
    

    ArrayList有四个内部类,其中的Itr是实现了Iterator接口,同时重写了里面的hasNext(), next(), remove() 等方法;
    其中的ListItr 继承 Itr,实现了ListIterator接口,同时重写了hasPrevious(),nextIndex(), previousIndex(), previous(), set(E e), add(E e) 等方法,所以这也可以看出了Iterator和ListIterator的区别:
    ListIterator在Iterator的基础上增加了添加对象,修改对象,逆向遍历等方法,这些是Iterator不能实现的。
    1.4 ArrayListDemo

    package list;
    import java.util.ArrayList;
    import java.util.Iterator; 
    public class ArrayListDemo { 
    	public static void main(String[] srgs){ 
    		ArrayList<Integer> arrayList = new ArrayList<Integer>(); 
    		System.out.printf("Before add:arrayList.size() = %d\n",arrayList.size());
    		arrayList.add(2); 
    		arrayList.add(4); 
    		arrayList.add(6); 
    		arrayList.add(8); 
    		arrayList.add(10); 
    		System.out.printf("After add:arrayList.size() = %d\n",arrayList.size());
    		// 三种遍历方式打印元素 
    		// 第一种:通过迭代器遍历 
    		System.out.print("通过迭代器遍历:"); 
    		Iterator<Integer> it = arrayList.iterator(); 
    		while(it.hasNext()){ 
    			System.out.print(it.next() + " "); 
    		}
    		System.out.println(); 
    		// 第二种:通过索引值遍历 
    		System.out.print("通过索引值遍历:"); 
    		for(int i = 0; i < arrayList.size(); i++){ 
    			System.out.print(arrayList.get(i) + " "); 
    		}
    		System.out.println(); 
    		// 第三种:for循环遍历 
    		System.out.print("for循环遍历:"); 
    		for(Integer number : arrayList){ 
    			System.out.print(number + " "); 
    		}
    		// toArray用法 
    		// 第一种方式(最常用) 
    		Integer[] integer = arrayList.toArray(new Integer[0]); 
    		// 第二种方式(容易理解) 
    		Integer[] integer1 = new Integer[arrayList.size()]; 
    		arrayList.toArray(integer1); 
    		// 抛出异常,java不支持向下转型 
    		//Integer[] integer2 = new Integer[arrayList.size()]; 
    		//integer2 = arrayList.toArray(); 
    		System.out.println(); 
    		// 在指定位置添加元素 
    		arrayList.add(2,2); 
    		// 删除指定位置上的元素 
    		arrayList.remove(2); 
    		// 删除指定元素 
    		arrayList.remove((Object)3); 
    		// 判断arrayList是否包含5 
    		System.out.println("ArrayList contains 5 is: " + arrayList.contains(5)); 
    		// 清空ArrayList arrayList.clear(); 
    		// 判断ArrayList是否为空 
    		System.out.println("ArrayList is empty: " + arrayList.isEmpty()); 
    		} 
    	}
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值