Java集合框架:ArrayList扩容机制解释

1、java中ArrayList该类的定义

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认容量为10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 空数组:用于调用带有容量切容量为0时初始化elementData这个值
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 空数组:用于调用空构造时初始化elementData这个值

     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     *数组变量
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * arrayList的长度
     */
    private int size;
   //后面自己需要看源码
   ...
}

2、ArrayList描述

    ArrayList是一个继承abstractList和实现List的接口的实现类。
    ArrayList是以数组实现的数组队列,允许重复。可以通过ArrayList来进行增加,删除,修改,遍历等操作。
    ArrayList可以说是一个动态数组。动态的最好例子可以说就是ArrayList的底层是数组,该数组的长度可以根据实际需要不断增加。

3、ArrayList的扩容机制

    3.1 对外提供的检查是否需要扩容方法

public void ensureCapacity(int minCapacity) {
//判断elementData是否是默认空数组,如果不是minExpand为0,如果是minExpand=DEFAULT_CAPACITY=10
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: DEFAULT_CAPACITY;
//如果我们预测的值比数组elementData数组的长度实际要大,需要扩容。只能说明我们需要更大容器的列表。
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }


3.2 内部实现的扩容机制

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//父类AbstractLisy生命的属性

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//我们需要的长度比elementData的长度大,扩容
            grow(minCapacity);
}
 private void grow(int minCapacity) {
	// overflow-conscious code
	int oldCapacity = elementData.length;//获取当前存放数据数组的长度
	int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容到原来数组长度的1.5倍
	if (newCapacity - minCapacity < 0)//如果扩容到长度的1.5倍以后,仍然不够用,直接将我们预计的值作为扩容长度
		newCapacity = minCapacity;
	if (newCapacity - MAX_ARRAY_SIZE > 0)//扩容上限最大值为Integer的最大值-8,如果超过这个最大值,使用下面的方法
		newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: 
	elementData = Arrays.copyOf(elementData, newCapacity);//使用数组Arrays的copyOf()进行扩容,每次扩容都采用System.arrayCopy()复制到新数组的 
}
private static int hugeCapacity(int minCapacity) {//如果扩容超过Integer.MAX_VALUE-8,代码会走该方法 
	if (minCapacity < 0) // overflow throw new OutOfMemoryError(); 
	//如果我们预测的长度比Integer.MAX_VALUE-8大,最后取Integer.MAX_VALUE。 
	return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE : MAX_ARRAY_SIZE; 
}

4、ArrayList遍历方式

                List<String> testList = new ArrayList<String>();
		testList.add("11");
		testList.add("21");
		testList.add("31");
		testList.add("41");
		testList.add("51");
		testList.add("61");
		testList.add("71");
		/**
		 * for循环遍历
		 */
		for(int index=0;index<testList.size();index++){
			System.out.println(testList.get(index));
		}
		System.err.println("===========foreach===========");
		/**
		 * foreach遍历
		 */
		for(String index:testList){
			System.out.println(index);
		}
		System.err.println("===========Iterator===========");
		/**
		 * 迭代器Iterator
		 */
		Iterator<String> iterator = testList.iterator();
		while(iterator.hasNext()){
			System.err.println(iterator.next());
		}
		

5、ArrayList和vector比较

普及:什么是线程安全什么是线程不安全

   线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

    线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。 如图,List接口下面有两个实现,一个是ArrayList,另外一个是vector。 从源码的角度来看,因为Vector的方法前加了,synchronized 关键字,也就是同步的意思,sun公司希望Vector是线程安全的,而希望arraylist是高效的,缺点就是另外的优点。

1、Vector每次扩容都是请求其大小的2倍空间,而ArrayList是1.5倍

2、Vector还有一个子类Stack





阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页