Arraylist 源码分析

  1. modcount 和 java的 Fail-Fast 机制有关 即为在可能发生错误的情况下提前抛出。

  2. transient Object[] elementData; // non-private to simplify nested class access
    

​ 这里的 non-private to simplify nested class access 翻译过来就是 非私有化以简化嵌套类访问 但是我们明明知道内部类明明可以透 明的访问内部类的所有成员,那么何谈简化呢?

​ 查看反编译字节码便可一探究竟:

​ 虚拟机不知道类的分组情况,会在类中提供非public方法以供内部类访问私有成员。内部类在访问外部类私有变量的同时,编译器会为外部类添加一个非公有方法,内部类通过持有外部类的引用,调用此方法,访问私有变量。

所以如果声明是非私有的,那么就可以简化编译器添加非公有方法的这个操作i,提高效率。这里的简化指的就是这个意思。

  1. private static final Object[] 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[] DEFAULTCAPCITY_EMPTY_ELEMENTDATA= {};
    

​ 关于EMPTY_ELEMENTDATA与DEFAULTCAPCITY_EMPTY_ELEMENTDATA的区别,其实中间的官方注释也解释了就是:

​ 我们将其(DEFAULTCAPCITY_EMPTY_ELEMENTDATA)与EMPTY_ELEMENTDATA数据区分开来,以了解添加第一个元素时要膨胀多少。

​ 这句话什么意思呢,我们看一下下面的源码就知道了:

Mylist是我对ArrayList的仿写 是一样的:

//无参构造构造直接赋值DEFAULTCAPCITY_EMPTY_ELEMENTDATA
public Mylist(){
    this.element=DEFAULTCAPCITY_EMPTY_ELEMENTDATA;
}
//  只有 initialCapactitty == 0 的时候才会赋值 EMPTY_ELEMENTDATA
public Mylist(int initialCapactity){
        if(initialCapactity > 0){
            this.element= new Object[initialCapactity];
        }else if(initialCapactity == 0){
            this.element=EMPTY_ELEMENTDATA;
        }else{
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapactity);
        }

    }
//  如果都第一次调用 add()  赋值的不同 将会带来下面函数的不同  

// 如果是  DEFAULTCAPCITY_EMPTY_ELEMENTDATA 则可以扩容到 10
//  如果是  EMPTY_ELEMENTDATA 则只会 增加到 1
private static int calculateCapacity(Object[] element, int minCapacity){
        //如果是空的 直接给10个空间 避免重复的grow;
        if(element == DEFAULTCAPCITY_EMPTY_ELEMENTDATA){
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

​ 4. 聊一聊ArrayList 的 动态扩容机制

public boolean add(E e){
    ensureCapacityInternal(size + 1);
    element[size++] = e;
    return true;
}

ArrayLIst的add()方法是如何保持空间足够的呢? 我们看到源码中一个关键函数 便是 ensureCapacityInternal 了

让我来看看ensureCapacityInternal的调用过程

private static int calculateCapacity(Object[] element, int minCapacity){
    //如果是空的 直接给10个空间 避免重复的grow;
    if(element == DEFAULTCAPCITY_EMPTY_ELEMENTDATA){
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
private void  ensureCapacityInternal(int minCapacity){
    ensureExplicitCapacity(calculateCapacity(element, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity){
    modCount++;

    // overflow-conscious code
    if(minCapacity - element.length >0)
        grow(minCapacity);                   //空间不够 扩容
}
// 最大数组大小  防止数组过大超过VM的限制
private  static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
 * 数组增长函数
 * @param minCapacity  需要的最小容量
 */
private void grow(int minCapacity){
   //  overflow-conscious code
    int oldCapacity = element.length;
    int newCapacity = oldCapacity +(oldCapacity >> 1);  //右移缩小一倍 懂得都懂 哈哈哈  还有一件事(1.5倍)
    if(newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if(newCapacity - MAX_ARRAY_SIZE > 0){
        newCapacity = hugeCapacity(minCapacity);
    }
}
private static int hugeCapacity(int minCapacity){
    if(minCapacity < 0) //overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
}

下面是函数的调用流程

在这里插入图片描述

核心就是 每次空间不够 就扩大1.5倍 在于 需要的 最小容量进行比较 如果还是不够 直接等于最小容量 如果最小容量超出了数组最大上限制, 在调用hugeCapacity 扩大到 Integer.MAX_VALUE 这是最大了。

//爱jdk 也爱jk
//To Be A Romantic Programmer

2021/4/26

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值