zoukankan      html  css  js  c++  java
  • JAVA-容器(3)-List

    (基于JDK1.8源码分析)

    一,List接口

      1,继承Collection接口,实现了集合的有序存储; 对元素位置进行精确控制,根据索引对集合进行访问和遍历;

      2,源码分析

    public interface List<E> extends Collection<E> {
    
        int size();
        boolean isEmpty();
        boolean contains(Object o);
        Iterator<E> iterator();
        Object[] toArray();
        <T> T[] toArray(T[] a);
        boolean add(E e);
        boolean remove(Object o);
        boolean containsAll(Collection<?> c);
        boolean addAll(Collection<? extends E> c);
        boolean addAll(int index, Collection<? extends E> c);
        boolean removeAll(Collection<?> c);
        boolean retainAll(Collection<?> c);
    
        /***/
        default void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            final ListIterator<E> li = this.listIterator();
            while (li.hasNext()) {
                li.set(operator.apply(li.next()));
            }
        }
    
        /***/
        @SuppressWarnings({"unchecked", "rawtypes"})
        default void sort(Comparator<? super E> c) {
            Object[] a = this.toArray();
            Arrays.sort(a, (Comparator) c);
            ListIterator<E> i = this.listIterator();
            for (Object e : a) {
                i.next();
                i.set((E) e);
            }
        }
    
        void clear();
        boolean equals(Object o);
        int hashCode();
    /** 返回指定索引位置元素*/ E get(int index); /** 设置指定索引位置元素*/ E set(int index, E element); /** 在指定索引位置新增元素*/ void add(int index, E element); /** 删除指定索引位置元素*/ E remove(int index); /** 返回指定对象最小索引位置*/ int indexOf(Object o); /** 返回指定对象最大索引位置,主要用于重复元素*/ int lastIndexOf(Object o); /** 返回迭代器默认索引位置为0; 支持前后遍历,原理是改变集合当前的索引位置*/ ListIterator<E> listIterator(); /** 返回迭代器并指定默认索引位置为index*/ ListIterator<E> listIterator(int index);
    /** 返回指定索引间的元素集合*/ List<E> subList(int fromIndex, int toIndex);
    /***/ @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, Spliterator.ORDERED); }

    二,ArrayList实现

      public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable

      RandomAccess: List实现使用的标记接口,用于提高连续或随机访问性能

      Cloneable: 实现Cloneable可以对该类实例进行克隆

      Serializable:用于表示可序列化

      【1】底层实现

             ArrayList底层通过数组实现

        transient Object[] elementData;  //transient避免Serializable持久化

      【2】构造方法

      /** 指定空间大小*/
        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);
            }
        }
        /** 默认空间大小为10*/
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
        /** 将指定集合转为数组  1-集合转数组  2-数组大小为0使用空数组替换  3-数组大小>0进行数组拷贝*/
        public ArrayList(Collection<? extends E> c) {
            elementData = c.toArray();
            if ((size = elementData.length) != 0) {
                // c.toArray might (incorrectly) not return Object[] (see 6260652)
                if (elementData.getClass() != Object[].class)
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
            } else {
                // replace with empty array.
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }

      【3】新增

      /** 设置指定索引位置元素    1-检查指定索引是否向前越界 2-获取指定索引位置原元素 3-将指定元素赋值到指定索引位置*/
        public E set(int index, E element) {
            rangeCheck(index);    //(index >= size)向前越界
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }
    
        /** 新增元素    1-容器扩容 2-将指定元素赋值到最大索引位置 */
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
    
        /** 新增元素到指定索引位置     1-检查索引是否越界 2-容器扩容 3-将指定索引位置右端元素右移 4-设置指定元素到指定索引位置*/
        public void add(int index, E element) {
            rangeCheckForAdd(index);    //(index > size || index < 0)越界
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }
      
    /** 新增集合中所有元素 1-将指定集合转数组 2-容器扩容 3-将转后数组添加到扩容前最大索引位置 4-容器扩容,大小为指定集合大小*/ 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; } /** 新增集合中所有元素到指定索引位置 1-检查指定索引越界 2-指定集合转数组 3-容器扩容 4-将扩容前最大索引位置右端元素右移 5-将换后数组添加到扩容前最大索引位置 6-容器扩容*/ public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); //(index > size || index < 0) 越界 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; }

       【4】查询

      /** 获取指定索引位置元素  1-检查索引向前越界 2-获取指定索引位置元素*/
        public E get(int index) {
            rangeCheck(index);   //(index >= size) 向前越界
    
            return elementData(index);
        }

        【5】删除  (①指定索引位置 ②指定元素)

      /** 删除指定索引位置元素  1-检查索引向前越界 2-获取删除后需要左移元素总数 3-将指定索引+1位元素左移 4-将最大索引位置空*/
        public E remove(int index) {
            rangeCheck(index);  //(index >= size) 向前越界
    
            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;
        }
    
        /** 删除指定元素在容器中首次出现的元素 */
        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;
        }
    
        /* 类似remove(int index)但是无索引越界检查 */
        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++;
    
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }

       【6】容器扩容

      /** 容器扩容-1 */
        public void ensureCapacity(int minCapacity) {
            int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                // any size if not default element table
                ? 0
                // larger than default for default empty table. It's already
                // supposed to be at default size.
                : DEFAULT_CAPACITY;
    
            if (minCapacity > minExpand) {
                ensureExplicitCapacity(minCapacity);
            }
        }
      /** 容器扩容-2*/
        private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
    
            ensureExplicitCapacity(minCapacity);
        }
    
        private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
    
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
    
      /** 新增元素集合之后的size > 集合容量,进行50%扩容 */
        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);
        }

        【7】将底层数组大小调整为实际集合中元素数量

        

     /**
         * Trims the capacity of this <tt>ArrayList</tt> instance to be the
         * list's current size.  An application can use this operation to minimize
         * the storage of an <tt>ArrayList</tt> instance.
         */
        public void trimToSize() {
            modCount++;
            if (size < elementData.length) {
                elementData = (size == 0)
                  ? EMPTY_ELEMENTDATA
                  : Arrays.copyOf(elementData, size);
            }
        }

        【8】Fail-fast(快速失败机制)

         modCount++  :记录修改此列表的次数(包括:修改列表元素,大小,顺序)

         定义:ArrayList是线程不安全的,如果使用迭代器过程中其他线程修改了List,会出现异常(ConcurrentModificationException)

        原理:ArrayList使用迭代器时,只允许迭代器对List进行remove,add,如果其他线程对List的修改迭代器会立刻出现异常,快速失败

        【9】迭代器

        checkForComodification(): 用于检查快速失败机制
        多线程同时操作同一个ArrayList时发现modCount不一致,出现快速失败ConcurrentModificationException异常
      /** 返回迭代器 */
        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(); } } @Override @SuppressWarnings("unchecked") public void forEachRemaining(Consumer<? super E> consumer) { Objects.requireNonNull(consumer); final int size = ArrayList.this.size; int i = cursor; if (i >= size) { return; } final Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) { throw new ConcurrentModificationException(); } while (i != size && modCount == expectedModCount) { consumer.accept((E) elementData[i++]); } // update once at end of iteration to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }

       【10】子列表 

        subList(int fromIndex, int toIndex)对子列表的修改会同时修改原列表
          List<String> a = new ArrayList<String>();
            a.add("a");
            a.add("b");
            a.add("c");
            a.add("d");
            List<String> a1 = a.subList(1, 2);
            a1.add("e");               //此操作会同时修改a和a1列表    a列表: a,b,e,c,d   a1列表:b,e
            a1.remove("b");            //此操作会同时修改a和a1列表    a列表: a,e,c,d     a1列表:e

        源码:

      /** 获取指定索引段之间的元素并以列表形式返回*/
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    
    
    
       private class SubList extends AbstractList<E> implements RandomAccess {
            private final AbstractList<E> parent;
            private final int parentOffset;
            private final int offset;
            int size;
    
            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;
            }
    
            public E set(int index, E e) {
                rangeCheck(index);
                checkForComodification();
                E oldValue = ArrayList.this.elementData(offset + index);
                ArrayList.this.elementData[offset + index] = e;
                return oldValue;
            }
    
            public E get(int index) {
                rangeCheck(index);
                checkForComodification();
                return ArrayList.this.elementData(offset + index);
            }
    
            public int size() {
                checkForComodification();
                return this.size;
            }
    
            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;
            }
    
            protected void removeRange(int fromIndex, int toIndex) {
                checkForComodification();
                parent.removeRange(parentOffset + fromIndex,
                                   parentOffset + toIndex);
                this.modCount = parent.modCount;
                this.size -= toIndex - fromIndex;
            }
    
            public boolean addAll(Collection<? extends E> c) {
                return addAll(this.size, c);
            }
    
            public boolean addAll(int index, Collection<? extends E> c) {
                rangeCheckForAdd(index);
                int cSize = c.size();
                if (cSize==0)
                    return false;
    
                checkForComodification();
                parent.addAll(parentOffset + index, c);
                this.modCount = parent.modCount;
                this.size += cSize;
                return true;
            }
    
            public Iterator<E> iterator() {
                return listIterator();
            }
    
            public ListIterator<E> listIterator(final int index) {
                checkForComodification();
                rangeCheckForAdd(index);
                final int offset = this.offset;
    
                return new ListIterator<E>() {
                    int cursor = index;
                    int lastRet = -1;
                    int expectedModCount = ArrayList.this.modCount;
    
                    public boolean hasNext() {
                        return cursor != SubList.this.size;
                    }
    
                    @SuppressWarnings("unchecked")
                    public E next() {
                        checkForComodification();
                        int i = cursor;
                        if (i >= SubList.this.size)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i + 1;
                        return (E) elementData[offset + (lastRet = i)];
                    }
    
                    public boolean hasPrevious() {
                        return cursor != 0;
                    }
    
                    @SuppressWarnings("unchecked")
                    public E previous() {
                        checkForComodification();
                        int i = cursor - 1;
                        if (i < 0)
                            throw new NoSuchElementException();
                        Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();
                        cursor = i;
                        return (E) elementData[offset + (lastRet = i)];
                    }
    
                    @SuppressWarnings("unchecked")
                    public void forEachRemaining(Consumer<? super E> consumer) {
                        Objects.requireNonNull(consumer);
                        final int size = SubList.this.size;
                        int i = cursor;
                        if (i >= size) {
                            return;
                        }
                        final Object[] elementData = ArrayList.this.elementData;
                        if (offset + i >= elementData.length) {
                            throw new ConcurrentModificationException();
                        }
                        while (i != size && modCount == expectedModCount) {
                            consumer.accept((E) elementData[offset + (i++)]);
                        }
                        // update once at end of iteration to reduce heap write traffic
                        lastRet = cursor = i;
                        checkForComodification();
                    }
    
                    public int nextIndex() {
                        return cursor;
                    }
    
                    public int previousIndex() {
                        return cursor - 1;
                    }
    
                    public void remove() {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();
    
                        try {
                            SubList.this.remove(lastRet);
                            cursor = lastRet;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    public void set(E e) {
                        if (lastRet < 0)
                            throw new IllegalStateException();
                        checkForComodification();
    
                        try {
                            ArrayList.this.set(offset + lastRet, e);
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    public void add(E e) {
                        checkForComodification();
    
                        try {
                            int i = cursor;
                            SubList.this.add(i, e);
                            cursor = i + 1;
                            lastRet = -1;
                            expectedModCount = ArrayList.this.modCount;
                        } catch (IndexOutOfBoundsException ex) {
                            throw new ConcurrentModificationException();
                        }
                    }
    
                    final void checkForComodification() {
                        if (expectedModCount != ArrayList.this.modCount)
                            throw new ConcurrentModificationException();
                    }
                };
            }
    
            public List<E> subList(int fromIndex, int toIndex) {
                subListRangeCheck(fromIndex, toIndex, size);
                return new SubList(this, offset, fromIndex, toIndex);
            }
    
            private void rangeCheck(int index) {
                if (index < 0 || index >= this.size)
                    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
    
            private void rangeCheckForAdd(int index) {
                if (index < 0 || index > this.size)
                    throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
    
            private String outOfBoundsMsg(int index) {
                return "Index: "+index+", Size: "+this.size;
            }
    
            private void checkForComodification() {
                if (ArrayList.this.modCount != this.modCount)
                    throw new ConcurrentModificationException();
            }
    
            public Spliterator<E> spliterator() {
                checkForComodification();
                return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                                   offset + this.size, this.modCount);
            }
        }

       【11】ArrayList和Vector区别

          ArrayList:异步

          Vector:同步

         同步:

            定义:多线程对于共享资源同一时间点只允许一个线程占用资源,其他线程等待 (线程安全)

            适用:多个线程共享同一个数据,就适用同步,否则会出现例如数据库脏读,不可重复读,幻读等现象

         异步:

            定义:只有一个线程访问当前数据     (线程不安全)

         

    package com.test;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Test implements Runnable {
        private ArrayList<String> aa = new ArrayList<String>();
    
        @Override
        public void run() {
            aa.set(0, "Thread");
        }
    
        public String get() {
            aa.add("ThreadMain");
            System.out.println(aa.get(0).toString());
            Iterator it = aa.iterator();
            return aa.get(0).toString();
        }
    
        public static void main(String[] args) throws InterruptedException {
    
            Test test = new Test();
            new Thread(test).start();
            System.out.println(test.get());
    
            /**
             * 执行结果: ThreadMain Thread
             */
    
        }
    
    }

          

  • 相关阅读:
    Flask程序相关配置加载的三种方式
    Redis数据库在windows系统下的安装及使用
    Redis数据库介绍
    python中模块的制作
    4.ORM框架的查询
    3.ORM框架一对多的关系及使用
    2.ORM框架添加,修改,删除操作
    1.ORM介绍,基本配置及通过ORM框架创建表
    4.集合
    3.字典
  • 原文地址:https://www.cnblogs.com/wanhua-wu/p/6653796.html
Copyright © 2011-2022 走看看