• ArrayList


    1、开始
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    继承了抽象类AbstractList,实现了List接口,RandomAccess接口(数据随机存储),Cloneable接口(可克隆),Serializable接口(可序列化)
    
    2、属性
        //用于存放元素的数组,不可进行序列化
        private transient Object[] elementData;
    
        //已经存放的元素的个数
        private int size;
    
    3、构造器
    
        //指定列表大小
         public ArrayList(int initialCapacity) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
            this.elementData = new Object[initialCapacity];
        }
    
        //默认列表大小为10
        public ArrayList() {
            this(10);
        }
    
        //有初始内容的列表
        public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();
            size = elementData.length;
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        }
    
     4、方法
    1)、添加
        //向列表中添加元素,返回是否添加成功
        public boolean add(E e) {
             //是否扩容
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    
        //向列表中指定的位置添加元素,其他的元素后移
        public void add(int index, E element) {
            //检测下标是否合法,下标范围[0,size]
            rangeCheckForAdd(index);
            //是否扩容
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1, size - index);
            elementData[index] = element;
            size++;
        }
    
    2)、获取和设置
        //根据下标返回元素
        E elementData(int index) {
            return (E) elementData[index];
        }
    
        //根据下标获取元素
        public E get(int index) {
            //检测下标是否合法,下标范围[0,size)
            rangeCheck(index);
    
            return elementData(index);
        }
    
        //设置列表中指定位置中的元素,并返回该位置的旧数据
        public E set(int index, E element) {
            //检测下标是否合法,下标范围[0,size)
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }
    3)、删除
        //删除指定位置的元素,并返回要删除的元素
         public E remove(int index) {
             //检测下标是否合法,下标范围[0,size)
            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; // Let gc do its work
    
            return oldValue;
        }
    
           //删除指定的元素,返回是否删除成功,分为删除的元素是否为null,之后分别进行遍历删除
        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);
            //利于GC
            elementData[--size] = null; // Let gc do its work
        }
    
    
    4)、扩容检测
        //目标容量与当前容量进行比较,是否进行扩容
        private void ensureCapacityInternal(int minCapacity) {
    
            //扩容相当于一次更改
            modCount++;
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
    
        /**
         * The maximum size of array to allocate.
         * Some VMs reserve some header words in an array.
         * Attempts to allocate larger arrays may result in
         * OutOfMemoryError: Requested array size exceeds VM limit
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
        //扩容,在原来的基础上增加0.5,即容量是原来的1.5倍
        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);
        }
    
        //获取最大的列表容量
        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }
    
    5)、范围检测
        
        //下标范围[0,size)
         /**
         * Checks if the given index is in range.  If not, throws an appropriate
         * runtime exception.  This method does *not* check if the index is
         * negative: It is always used immediately prior to an array access,
         * which throws an ArrayIndexOutOfBoundsException if index is negative.
         */
        private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
    
        //下标范围[0,size],用于add(index)与addAll方法
        /**
         * A version of rangeCheck used by add and addAll.
         */
        private void rangeCheckForAdd(int index) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
        /**
         * Constructs an IndexOutOfBoundsException detail message.
         * Of the many possible refactorings of the error handling code,
         * this "outlining" performs best with both server and client VMs.
         */
        private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+size;
        }
    
    6)、获取集合间的交集和差集
    
        //集合差集
         public boolean removeAll(Collection<?> c) {
            return batchRemove(c, false);
        }
    
        //集合交集
        public boolean retainAll(Collection<?> c) {
            return batchRemove(c, true);
        }
    
        //集合间的操作
        private boolean batchRemove(Collection<?> c, boolean complement) {
            final Object[] elementData = this.elementData;
            int r = 0, w = 0;
            boolean modified = false;
            try {
                for (; r < size; r++)
                    if (c.contains(elementData[r]) == complement)
                        elementData[w++] = elementData[r];
            } finally {
                // Preserve behavioral compatibility with AbstractCollection,
                // even if c.contains() throws.
                if (r != size) {
                    System.arraycopy(elementData, r, elementData, w, size - r);
                    w += size - r;
                }
                if (w != size) {
                    for (int i = w; i < size; i++)
                        elementData[i] = null;
                    modCount += size - w;
                    size = w;
                    modified = true;
                }
            }
            return modified;
        }
    
    7)、将集合添加到列表中
        
        //将集合添加到列表末尾
        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;
        }
    
    
    8)、基础方法
    
        //获取列表元素个数
        public int size() {
            return size;
        }
    
        //列表是否为空,即大小是否为0
        public boolean isEmpty() {
            return size == 0;
        }
    
        //列表是否包含该元素
        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;
        }
    
        //查找元素在列表中的最后一次出现的位置,倒序遍历
        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;
        }
    
        //将列表转换为数组
        public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }
    
        //将列表转换给指定的数组
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            if (a.length < size)
                // Make a new array of a's runtime type, but my contents:
                return (T[]) Arrays.copyOf(elementData, size, a.getClass());
            System.arraycopy(elementData, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }
    
        //缩减列表中不存在的元素
        public void trimToSize() {
            modCount++;
            int oldCapacity = elementData.length;
            if (size < oldCapacity) {
                elementData = Arrays.copyOf(elementData, size);
            }
        }
    
    9)、迭代器,都支持fail-fast机制,可能会抛出ConcurrentModificationException异常
        //列表迭代器
        public ListIterator<E> listIterator(int index) {
            if (index < 0 || index > size)
                throw new IndexOutOfBoundsException("Index: "+index);
            return new ListItr(index);
        }
    
        //列表迭代器
        public ListIterator<E> listIterator() {
            return new ListItr(0);
        }
    
        //迭代器
        public Iterator<E> iterator() {
            return new Itr();
        }
    
        //迭代器定义
        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;
    
            //是否还有元素
            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();
                }
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }

     //列表迭代器定义
     private class ListItr extends Itr implements ListIterator<E> {
            ListItr(int index) {
                super();
                cursor = index;
            }
            //是否有前一个
            public boolean hasPrevious() {
                return cursor != 0;
            }
    
            //获取下一个索引
            public int nextIndex() {
                return cursor;
            }
    
            //获取前一个索引
            public int previousIndex() {
                return cursor - 1;
            }
    
            //获取前一个元素
            @SuppressWarnings("unchecked")
            public E previous() {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i;
                return (E) elementData[lastRet = i];
            }
    
            //设置元素
            public void set(E e) {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    ArrayList.this.set(lastRet, e);
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
    
            //添加元素
            public void add(E e) {
                checkForComodification();
    
                try {
                    int i = cursor;
                    ArrayList.this.add(i, e);
                    cursor = i + 1;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
        }
    
    
    
    10)、子列表,更改子列表时,会影响到父列表,但更改父列表时,子列表将抛出异常ConcurrentModificationException
        //获取子列表
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    
        //子列表检测
        static void subListRangeCheck(int fromIndex, int toIndex, int size) {
            if (fromIndex < 0)
                throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
            if (toIndex > size)
                throw new IndexOutOfBoundsException("toIndex = " + toIndex);
            if (fromIndex > toIndex)
                throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                                   ") > toIndex(" + toIndex + ")");
        }
    
        //以下是子列表对象中的方法
    
        //子列表构造器
        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;//父列表对象
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;//子列表大小
            this.modCount = ArrayList.this.modCount;
            //子列表更改记录,必须跟父列表保持同步,否则抛出异常ConcurrentModificationException
        }
    
        //往指定位置添加元素
        public void add(int index, E e) {
            rangeCheckForAdd(index);
            checkForComodification();
            //往父列表中添加元素后,需要将更改记录同步到子列表中
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        }
    
        //删除指定位置的元素
        public E remove(int index) {
            rangeCheck(index);
            checkForComodification();
            E result = parent.remove(parentOffset + index);
            //往父列表中删除元素后,需要将更改记录同步到子列表中
            this.modCount = parent.modCount;
            this.size--;
            return result;
        }
    
        //检测子列表与父列表的更改状态是否一致
           private void checkForComodification() {
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        }
    ArrayList的遍历方式
    1)、根据索引值进行遍历
    2)、通过迭代器进行遍历
    3)、通过foreach
    
    ArrayList和LinkedList
    1)、ArrayList是基于动态数组实现的数据结构,而LinkedList是基于链表实现的数据结构
    2)、对于随机访问get和set,ArrayList优于LinkedList,这是由于LinkedList需要移动指针
    3)、对于新增和删除操作add和remove,LinkedList比较占优势,这是由于ArrayList需要移动数据
    
    ArrayList和Vector
    1)、Vector和ArrayList实现几乎一样,唯一不同的是Vector是同步类(synchronized),故开销比ArrayList大,访问慢
    2)、Vector每次扩容后其大小是原来的2倍,而ArrayList是1.5倍
    3)、Vector还有一个子类Stack

    参考资料:

    http://www.importnew.com/17440.html

    http://anxpp.com/index.php/archives/664/

  • 相关阅读:
    正则表达式简介
    每个程序员都必须遵守的编程原则
    String, StringBuffer, StringBuilder
    一些软件设计的原则
    A hard puzzle ACM HDU1097
    ACM HDU 1032The 3n + 1 problem
    Humble Numbers HDU 1058 ACM
    ACM HDU 1028Ignatius and the Princess III
    HangOver ACM HDU1056
    ACM HDU 1021Fibonacci Again
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/5604399.html
Copyright © 2020-2023  润新知