分析java.util.ArrayList的内存分配


看源码:java.util.ArrayList.class文件,进行分析:

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;//默认的初始化数组长度默认是10

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};//空数组,当调用无参数构造函数的时候默认给个空数组.

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
     * DEFAULT_CAPACITY when the first element is added.
     */
    private transient Object[] elementData;// 真正用来存元素的数组

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;//ArrayList集合的大小/元素的数量.


//无参构造器:默认给个空数组
//调用如 ArrayList a = new ArrayList(); ArrayList<String> strA = new ArrayList<String>();
    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

//带参数(初始大小)的构造器:initialCapacity 指定数组长度
//调用如 ArrayList b = new ArrayList(3); ArrayList<String> strB = new ArrayList<String>(6);
    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

//带对象参数的构造器:将Collection里面的值copy到arrayList
    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }


//---------------添加操作的流程Start:--------------------------------
    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e; // 将对象e放入elementData数组中下标为size的位置, size自加1.
        return true;
    }


    //传入参数 minCapacity = size + 1;//可理解为 将要放入 数组位置的下标
    private void ensureCapacityInternal(int minCapacity) {
    //如果用于存元素的数组elementData等于空(调用ArrayList无参构造器时 默认给的空数组),则要初始化它
        if (elementData == EMPTY_ELEMENTDATA) {
    //用Math的max函数比较得出(默认值10,minCapacity)谁更大,取最大值传入ensureExplicitCapacity方法。
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

// 当ArrayList里的elementData空间不够放时,则调用grow方法增大空间;
// 存前9个时 if都是false、 不增大, 存第十个时 minCapacity=11 、if为true、增大;  
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++; //基类的变量,初始值0.

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }


private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//2147483639
    Integer的MAX_VALUE:public static final int   MAX_VALUE = 0x7fffffff;

//
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // ">>"是"带符号的右移";
        // "n >> 1"相当于 "n除以2";
        // newCapacity = oldCapacity乘以1.5。

//再判断一下新数组的容量够不够,够了就直接使用minCapacity这个长度创建新数组,
//不够就将数组长度设置为需要的长度
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity; // 无参构造的list对象第一次add时 走这里.

        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);//新new一个[newCapacity]Object数组,将原数组内容拷贝过去.
    }

//----------添加操作的流程- END ----------------------------
    
    
    //修整elementData数组的长度,一般是当这个List集合装载完毕 不需要再装入东西时 调用一下,以节省资源.
    /**
     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an <tt>ArrayList</tt> instance.
     */
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = Arrays.copyOf(elementData, size);
        }
    }


使用无参构造函数分配的存储数据的数组长度是10,
每接近一次elementData.length,进行按照当前数组长度的1.5倍进行分配内存大小,并将数据从一个数组拷贝到新数组。

所以,调用ArrayTest()构造器,存放元素时候,默认的数组长度变化:10;15;22;

为了不浪费内存,如果能预先估计需要存储到ArrayList的数据量,推荐使用public ArrayList(int initialCapacity)进行初始化。

或者也可以用ArrayList的trimToSize方法减去浪费的内存(但是重新排一遍也会耽误一定的性能)。


下面,我们可以自定义一个ArrayList:定义一个ArrayTest类

package com.mylist;

import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;

/**
 * 自定义的ArrayTest类
 * @ProjectName:TestProject201609
 * @FileName: ArrayTest.java
 * @Description:ArrayTest
 * @version 0.1
 * @author Ally
 * @date 2016年09月28日
 */
public class ArrayTest<E>  extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
	
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;//默认的初始化数组长度默认是10

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};//空数组,当调用无参数构造函数的时候默认给个空数组.

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
     * DEFAULT_CAPACITY when the first element is added.
     */
    private transient Object[] elementData;// 真正用来存元素的数组

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;//ArrayList集合的大小/元素的数量.


//无参构造器:默认给个空数组(length=0)
//调用如 ArrayList a = new ArrayList(); ArrayList<String> strA = new ArrayList<String>();
    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayTest() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
        System.out.println("--- 调用 构造器- ArrayTest();"+" elementData长度="+elementData.length);
    }

//带参数(初始大小)的构造器:initialCapacity 指定数组长度
//调用如 ArrayList b = new ArrayList(3); ArrayList<String> strB = new ArrayList<String>(6);
    public ArrayTest(int initialCapacity) {
        super();
        System.out.println("--- 调用 构造器- ArrayTest(int initialCapacity)");
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }


//带对象参数的构造器:将Collection里面的值copy到arrayList
    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayTest(Collection<? extends E> c) {
    	System.out.println("--- 调用 构造器- ArrayTest(Collection<? extends E> c) ");
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }


//---------------添加操作的流程Start:--------------------------------
    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    	System.out.println("--ArrayTest添加元素 Start--》 size="+size +"; elementData长度="+elementData.length);
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e; // 将对象e放入elementData数组中下标为size的位置, size自加1.
        System.out.println("--ArrayTest添加元素 END--》 size="+size +"; elementData长度="+elementData.length);
        return true;
    }


    //传入参数 minCapacity = size + 1;//可理解为 将要放入 数组位置的下标
    private void ensureCapacityInternal(int minCapacity) {
    	System.out.println("ensureCapacityInternal方法》》传入的minCapacity="+minCapacity);
    	//如果用于存元素的数组elementData等于空(调用ArrayList无参构造器时 默认给的空数组),则要初始化它
        if (elementData == EMPTY_ELEMENTDATA) {
        	System.out.println("elementData == EMPTY_ELEMENTDATA");
        	//用Math的max函数比较得出(默认值10,minCapacity)谁更大,取最大值传入ensureExplicitCapacity方法。
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

	// 当ArrayList里的elementData空间不够放时,则调用grow方法增大空间;
	// 存前9个时 if都是false、 不增大, 存第十个时 minCapacity=11 、if为true、增大; 
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++; //基类的变量,初始值0.

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }


private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//2147483639
//    Integer的MAX_VALUE:public static final int   MAX_VALUE = 0x7fffffff;

	// 
    private void grow(int minCapacity) {
    	System.out.println("进入grow方法:");
        // overflow-conscious code
        int oldCapacity = elementData.length;
        /**
			">>"是"带符号的右移";
			"n >> 1"相当于 "n除以2";
			newCapacity = oldCapacity乘以1.5。
         */
        int newCapacity = oldCapacity + (oldCapacity >> 1);

		/**
		再判断一下新数组的容量够不够,够了就直接使用minCapacity这个长度创建新数组, 
		不够就将数组长度设置为需要的长度
		 */
        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);//新new一个[newCapacity]Object数组,将原数组内容拷贝过去.
//        	elementData = copyOf(elementData, newCapacity);
        System.out.println("oldCapacity="+oldCapacity);
        System.out.println("newCapacity="+newCapacity);
        System.out.println("grow方法结束. elementData长度="+elementData.length);
    }
    
//-------------------添加操作的流程- END -------------------------------------------------------
    
    
    //修整elementData数组的长度,一般是当这个List集合装载完毕 不需要再装入东西时 调用一下,以节省资源.
    /**
     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an <tt>ArrayList</tt> instance.
     */
    public void trimToSize() {
        modCount++;
        System.out.println("=== trimToSize调用前:size="+size + "; elementData数组长度="+elementData.length);
        if (size < elementData.length) {
            elementData = Arrays.copyOf(elementData, size);
        }
        System.out.println("=== trimToSize调用结束:size="+size + "; elementData数组长度="+elementData.length);
    }


	@Override
	public int size() {
		return size;
	}


	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return false;
	}


	@Override
	public boolean contains(Object o) {
		// TODO Auto-generated method stub
		return false;
	}


	@Override
	public Iterator<E> iterator() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object[] toArray() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public <T> T[] toArray(T[] a) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public boolean remove(Object o) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean addAll(int index, Collection<? extends E> c) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		// TODO Auto-generated method stub
		return false;
	}




	@Override
	public boolean retainAll(Collection<?> c) {
		// TODO Auto-generated method stub
		return false;
	}




	@Override
	public void clear() {
		// TODO Auto-generated method stub
		
	}




	@Override
	public E get(int index) {
		// TODO Auto-generated method stub
		return null;
	}




	@Override
	public E set(int index, E element) {
		// TODO Auto-generated method stub
		return null;
	}




	@Override
	public void add(int index, E element) {
		// TODO Auto-generated method stub
		
	}




	@Override
	public E remove(int index) {
		// TODO Auto-generated method stub
		return null;
	}




	@Override
	public int indexOf(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}




	@Override
	public int lastIndexOf(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}




	@Override
	public ListIterator<E> listIterator() {
		// TODO Auto-generated method stub
		return null;
	}




	@Override
	public ListIterator<E> listIterator(int index) {
		// TODO Auto-generated method stub
		return null;
	}




	@Override
	public List<E> subList(int fromIndex, int toIndex) {
		// TODO Auto-generated method stub
		return null;
	}

    
    
	
}



 

测试一下效果:

package com.mylist;
/**
 * @ProjectName:TestProject201609
 * @FileName: AmyT.java
 * @Description:AmyT
 * @version 0.1
 * @author AllyLai
 * @date 2016年09月28日
 */
public class AmyT {
	
	public static void main(String args[]) {  
//		int oldCapacity = 10;
//		int newCapacity = oldCapacity + (oldCapacity >> 1);
//		System.out.println(newCapacity);//15
		
		
		//走ArrayTest()构造器:
		ArrayTest a = new ArrayTest();
//		ArrayTest<String> a = new ArrayTest<String>();
		
		
		//走ArrayTest(int initialCapacity)构造器:
//		ArrayTest a = new ArrayTest(6);
//		ArrayTest<String> a = new ArrayTest<String>(6);
		
		a.add("1号");
		a.add("2号");
		a.add("3号");
		a.add("4号");
		a.add("5号");
		a.add("6号");
		a.add("7号");
		a.add("8号");
		a.add("9号");
		a.add("10号");
		a.add("11号");
		a.add("12号");
		a.add("13号");
		a.add("14号");
		a.add("15号");
		a.add("16号");
		a.add("17号");
		a.add("18号");
		a.add("19号");
		a.add("20号");
		a.add("21号");
		a.add("22号");
		a.add("23号");
		
		a.trimToSize();
		
	}

}











评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值