分析java.util.ArrayList的内存分配,
分享于 点击 42141 次 点评:120
分析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();
}
}
相关文章
- 暂无相关文章
用户点评