栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java集合——ArrayList 源码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java集合——ArrayList 源码

1、jdk1.6关键源码:
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{

    // 底层Object数组
    private transient Object[] elementData;

    // 数组有效元素个数
    private int size;

    // 指定大小构造器
    public ArrayList(int initialCapacity) {
	    super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
	    this.elementData = new Object[initialCapacity];
    }

    // 默认构造器
    public ArrayList() {
	    this(10);
    }

    
    public ArrayList(Collection 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);
    }

    // 添加元素
    public boolean add(E e) {
	    ensureCapacity(size + 1); 
	    elementData[size++] = e;
	    return true;
    }

    // 数组扩容的关键方法
    public void ensureCapacity(int minCapacity) {
	    modCount++;
	    int oldCapacity = elementData.length;
	    if (minCapacity > oldCapacity) {
	        Object oldData[] = elementData;
	        int newCapacity = (oldCapacity * 3)/2 + 1;
    	        if (newCapacity < minCapacity)
		            newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
	    }
    }

    // get方法
    public E get(int index) {
	    RangeCheck(index); // 判断数组下标

	    return (E) elementData[index];
    }
    
    // 直接使用索引下标获取
    E elementData(int index) {
        return (E) elementData[index];
    }

    ......
}

总结jdk1.6源码:

        1)调用默认构造器时,就给默认大小是10;

        2)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = (oldCapacity * 3)/2 + 1)。

数组扩容原理图:

2、jdk1.7关键源码
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{

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

    // 空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 底层Object数组
    private transient Object[] elementData;

    // 数组有效大小
    private int size;

    // 默认构造器
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

    // add方法
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 保证数组容量和扩容!!
        elementData[size++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        // 第一次添加元素的时候,给数组赋予最小大小为10
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 扩容
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    // 数组最大大小
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // 数组扩容的关键方法
    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);
    }

    // get方法
    public E get(int index) {
	    RangeCheck(index); // 判断数组下标

	    return (E) elementData[index];
    }
    
    // 直接使用索引下标获取
    E elementData(int index) {
        return (E) elementData[index];
    }

    ......

}

 总结jdk1.7源码:

        1)调用默认构造器时,elementData数组是一个空数组{};

        2)当第一次调用add方法添加元素时,才创建一个大小为10的数组;

        3)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1))。

数组扩容原理图:同 jdk1.6

3、jdk1.8关键源码
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{

    // 默认初始大小
    private static final int DEFAULT_CAPACITY = 10;

    // 空实例数组
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 默认大小的空实例数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 实际保存值的对象数组
    transient Object[] elementData; 

    // 实际对象元素个数
    private int size;

    // 在jdk1.8中调用空构造器的时候,是默认空数组
    public ArrayList() { 
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // add 方法
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 确保数组容量和扩容,修改计数加1!!
        elementData[size++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }


    // 数组最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // 数组扩容的关键方法
    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);
    }

    // get方法
    public E get(int index) {
	    RangeCheck(index); // 判断数组下标

	    return (E) elementData[index];
    }
    
    // 直接使用索引下标获取
    E elementData(int index) {
        return (E) elementData[index];
    }

    ......

}

 总结jdk1.8源码:

        1)调用默认构造器时,elementData数组是一个空数组{};

        2)当第一次调用add方法添加元素时,才创建一个大小为10的数组;

        3)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1))。

(虽然jdk1.8和jdk1.7在add方法的源码上有细微区别,但是本质上是一样的)

数组扩容原理图:同 jdk1.6

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/658499.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号