JAVA常用集合总结 ArrayList

ArrayList 源码分析扩容过程及性能优化

ArrayList 默认初始化过程,初始容量为10的空列表
	 //首先我们看源码,无参构造函数
     /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    
    //DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的初始化
    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
     
     //可以再看一下add方法中,调用的ensureCapacityInternal方法中判断elementData == EMPTY_ELEMENTDATA 是否为空,如果为空,minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);,minCapacity设置为其中的大值,在默认是空的时候,初次调用add方法传入的参数是1,也就是这里的minCapacity就是1,现在minCapcity变成了DEFAULT_CAPACITY 也就是10
     public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
     private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
     
     //默认值
     /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

ArrayList的扩容规律

通过下面的源码发现,如果空间不够,会通过Arrays.copyOf()创建一个新的内存空间,新空间的大小最小为原空间的1.5倍,这里是通过位移运算,效果相当于 
oldCapacity/2 = oldCapacity >> 1 
 	/**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    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);
    }

通过以上源码可以看到,ArrayList是非常浪费内存的,当集合太大的时候,很容易出现OOM 那么在知道List长度范围的情况下,在实例化ArrayList的时候带上长度 new ArrayList(256),来 降低内存碎片和内存拷贝次数。 当文本内容或者Excel大量导入场景时,可以考虑先做分段处理,而不是一次导入到内存中

Vector

vector 初始化大小也是10,与ArrayList 不同的是动态策略不同,和加有synchronized关键字确定方法临界区,使线程同步

    public Vector() {
        this(10);
    }
 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }

LinkedList

LinkedList 的数据结构为双向链表,双向链表与数组的优点为,遍历 删除 元素 都优与动态数组的ArrayList

java集合说得很好的一篇博文

猜你喜欢

转载自my.oschina.net/Alexyeh/blog/1798456