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

    ArrayList

    • ArrayList是基于数组实现的List
    • 是有序的
    • 每次添加之前判断是否进行扩容
    • 不是线程安全的。

    构造方法

    // 空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    
    // 簿制定大小的初始化,初始化为一个空数组
    public ArrayList() {
    	// super 方法为空
        super();
        // 初始化list为一个空数组,在add的ensureCapacityInternal进行初始化
        this.elementData = EMPTY_ELEMENTDATA;
    }
    
    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
    	// 将list初始化为制定大小                                           
        this.elementData = new Object[initialCapacity];
    }
    
    // 从一个collection创建一个list
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        // http://blog.csdn.net/aitangyong/article/details/30274749
        // 大致意思就是c.toArray返回的不一定是Object[],所以需要进行判断
        if (elementData.getClass() != Object[].class)
        	// 如果不是Object数组复制到一个Object数组
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    
    

    add

    在查看add方法之前,先看看ArrayList父类AbstractList的一个属性modCount
    protected transient int modCount = 0;
    modCount是用来记录list改变的次数(add,remove,addAll etc.),这个值是被Iterator和ListIterator使用,用来检查在遍历list的时候list是否发生变化,也就是是否存在并发访问的情况。如果一个线程在遍历的时候,另一个线程进行add和remove,会造成遍历出错抛出ConcurrentModificationException

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
    
        ensureExplicitCapacity(minCapacity);
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
    	// 每次add的时候都会增加modCount
        modCount++;
    
        // overflow-conscious code
        // 如果原来的数组已经满了,则进行扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    // list扩容
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 每次扩容为原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
        	// 当一开始数组大小为1的时候会出现,即elementData.length = 1
            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
        	// minCapacity可能会溢出,Integer.MAX_VALUE + 1就是负的
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
    

    get

    public E get(int index) {
    	// 检查数组下标是否越界
        rangeCheck(index);
    	// 使用数组下标直接访问
        return elementData(index);
    }
    

    set 替换原来index位置的元素

    public E set(int index, E element) {
        rangeCheck(index);
    
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
    

    remove

    public E remove(int index) {
        rangeCheck(index);
    	// 删除的时候也需要对modCount加1,因为modCOunt记录的是list的改变次数,remove也会改变list
        modCount++;
        // 记录下被删除的元素,下面返回
        E oldValue = elementData(index);
    
        int numMoved = size - index - 1;
        if (numMoved > 0)
        	// copy的时候跳过要删除的元素
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    
        return oldValue;
    }
    
  • 相关阅读:
    读书笔记之理想设计的特征
    一些javascript 变量声明的 疑惑
    LINQ 使用方法
    Google MySQL tool releases
    读书笔记之设计的层次
    EF之数据库连接问题The specified named connection is either not found in the configuration, not intended to be used with the Ent
    转载 什么是闭包
    javascript面向对象起步
    Tips
    数据结构在游戏中的应用
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/6115867.html
Copyright © 2011-2022 走看看