zoukankan      html  css  js  c++  java
  • 集合—ArrayList

    ArrayList也叫作数组列表

     public static void main(String[] args) {
            List list1 = new ArrayList<String>();
            list1.add("a");
            //0100=4 右移1位 0010=2
            System.out.println(4>>1); //相当于 4/2
            //0010=2 左移1位 0100=4
            System.out.println(2<<1); //相当于 2*2
            
        }
      
        transient Object[] elementData;
        private int size;
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        /**
         * Default initial capacity.
         */
        private static final int DEFAULT_CAPACITY = 10;
        protected transient int modCount = 0;
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        public boolean add(E e) {
            // 保证数组的容量始终够用
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            // size是elementData数组中元素的个数,初始化为0
            elementData[size++] = e;
            return true;
        }
        
        private void ensureCapacityInternal(int minCapacity) {
            // 如果数组没有元素,给数组一个默认大小,会选择实例化时的值与默认大小中较大值
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            // 保证容量够用
            ensureExplicitCapacity(minCapacity);
        }
        
        private void ensureExplicitCapacity(int minCapacity) {
            // modCount是elementData数组发生size更改的次数
            modCount++;
            // 如果当前数组长度比原数组长度大,则进行扩容
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
        
        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;
            // 新的数组长度 会进行行1.5倍扩容,通过向右移位实现/2操作
            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:这里只用Arrays.copyOf
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
        
        public void add(int index, E element) {
            // 判断index的值是否合法,如果不合法则抛出异常
            rangeCheckForAdd(index);
            // 保证容量够用
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            // 从第index位置开始,将元素往后移一个位置
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            // 把要插入的元素e放在第index的位置
            elementData[index] = element;
            // 数组的元素个数加1
            size++;
        }
        
        /**
         * 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;
        }

    ArrayList是基于数组实现的,是一个动态数组,其容量能够自动增长 ArrayList不是线程安全的,只能用在单线程环境下,多线程环境需要使用Collections同步方法。Collections.synchronizedList(List l)返回一个线程安全的ArrayList。如果是读写比例比较大的话(锁粒度降级),则可以考虑CopyOnwriteArrayList。

    1. 默认容量是10
    2. ArrayList每次增加元素的时候,都需要调用ensureCapacity方法来确保足够的容量。当容量不足的时候,就设置新的容量为旧的的容量的1.5倍加1,如果设置的容量仍然不够,那么直接设置为传入的参数,而后用Arrays.copyOf方法将元素拷贝到新的数组。建议:在能够实现确定元素数量的情况下使用ArrayList,否则使用LinkedList。
    3. Arrays.copy()方法在方法的内部又创建了一个长度等长的数组,调用System.arraycopy方法完成新数组元素的复制。该方法的实际上调用native方法中C的memmove函数,在复制大数组的时候强烈建议使用该方法进行数组的复制。效率高。
    4. ArrayList是基于数组实现的,支持随机访问,查找效率高,但是插入删除效率低。
    5. ArrayList一般应用于查询较多但插入以及删除较少情况,如果插入以及从删除较多则建议使用LinkedList.
    6. ArrayList在知道长度范围实例化的时候带上长度 new ArrayList(128),这样降低了内存碎片和内存拷贝的次数.
  • 相关阅读:
    Spring@Profile注解
    day 32 子进程的开启 及其用法
    day 31 udp 协议SOCK_DGRAM
    day 30 客户端获取cmd 命令的步骤
    day 29 socket 理论
    day 29 socket 初级版
    有关 组合 继承
    day 27 多态 接口 类方法 静态方法 hashlib 摘要算法模块
    新式类和经典类的区别
    day 28 hasattr getattr serattr delattr 和带__内置__ 类的内置方法
  • 原文地址:https://www.cnblogs.com/atomicbomb/p/9917076.html
Copyright © 2011-2022 走看看