zoukankan      html  css  js  c++  java
  • ArrayList

    1. 基本属性

      底层使用动态数组实现

            //集合的默认大小
            private static final int DEFAULT_CAPACITY = 10;
            //空的数组实例
            private static final Object[] EMPTY_ELEMENTDATA = {};
            //这也是一个空的数组实例,和EMPTY_ELEMENTDATA空数组相比是用于了解添加元素时数组膨胀多少
            private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
            //存储 ArrayList集合的元素,集合的长度即这个数组的长度
            //1、当 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 时将会清空 ArrayList
            //2、当添加第一个元素时,elementData 长度会扩展为 DEFAULT_CAPACITY=10
            transient Object[] elementData;
            //表示集合的长度
            private int size;

    1.1 DEFAULTCAPACITY_EMPTY_ELEMENTDATA

      无参构造器中初始化数组

    public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }

      确定扩容后的大小

      // 确定容量大小
        private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            ensureExplicitCapacity(minCapacity);
        } 

    2. 扩容

       // 添加元素
       public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
        // 数组是否等于 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        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);
        }
    
        // 有些VM会在数组中保留一些标题字。尝试分配更大的数组可能会导致OutOfMemoryError:请求的数组大小超过VM限制
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        // 扩容
        private void grow(int minCapacity) {
            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;
        }

    3. subList

        // 注意:返回的是原集合的视图,也就是说,如果对 subList 出来的集合进行修改或新增操作,那么原始集合也会发生同样的操作。
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
        // 返回列表中指定的 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;
            }
       }

    4. 迭代器

      此类的 iteratorlistIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 removeadd 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

    private class Itr implements Iterator<E> {
            // 返回元素的下标,从0开始递增
            int cursor;    
            // 判断是否可以执行remove操作    
            int lastRet = -1; 
            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();
                // 数组下标 + 1
                cursor = i + 1;
                // lastRet = 当前返回元素的下标
                return (E) elementData[lastRet = i];
            }
    
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    ArrayList.this.remove(lastRet);
                    // 元素删除后游标重新赋值
                    cursor = lastRet;
                    // remove必须在next之后执行
                    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() {
                // 快速失败
                // 遍历时只能通过remove删除元素,且不能通过其他操作从结构上改变数组
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }

      

  • 相关阅读:
    springboot笔记
    SpringBoot
    SpringBoot整合JPA
    Docker
    SpringMVC学习04:异常处理和拦截器
    SpringMVC学习03:文件上传
    SpringMVC学习02:响应数据和结果视图
    Mybatis学习04
    【java基础】初步理解面向对象、类、对象
    【Java基础】方法的重载
  • 原文地址:https://www.cnblogs.com/virgosnail/p/9451773.html
Copyright © 2011-2022 走看看