Java集合(ArrayList)源码分析之一

 想提升自己的java基础,但是不知道从何看起,因为自己很多东西只略知一二,很少去深究,基础薄弱。搜索如何学好Java基础,大多数都是提议查看源码,说实话我曾经几次想看源码的,但是还是害怕就放弃了。这一次,又鼓足勇气打开了java源码,这次我看的、学到的知识都会记录在此。我大概清楚java基础的几大重要模块:

  1. 集合
  2. 多线程
  3. I/O
  4. 网络
    就先从集合开始看。

 关于什么是集合,什么是ArrayList…这里就不再赘述了,网上太多了。只记录自己觉得不熟悉,看了几遍才看懂的东西。


ArrayList

	transient Object[] elementData; 

基于数组实现。

特点:

有序、可重复、查询较快、增删慢、不是线程安全。

fail-first

ArrayList采用的是fail-first。

fail-first 一种错误机制,当多个线程同时操作同一集合的内容就可能会发生。
原理:利用modCount,每次修改内容modCount++, 那么在迭代器的初始化过程中就会将这个值赋值给迭代器的expectedModCount, 判断modCount与expectedModCount的值是否相等,不相等就报 ConcurrentModificationException

一些方法的用途(以前没有接触的):

trimToSize()将当前列表大小最小化。当前的列表就是当前元素的个数。

foreach()结合 lambda表达式(后续了解)进行使用。

源码呈上

构造函数(这里就不呈上源码了)

  1. public ArrayList(Collection<? extends E> c) //复制其他Collection中的值
  2. public ArrayList(int initialCapacity) //初始化容量的大小
  3. public ArrayList() //使用初始容量的大小

扩容(重要)

这里就是数组与ArrayList的一个重要区别,后者可以自动扩容而前者不行

 //初始容量的大小
 private static final int DEFAULT_CAPACITY = 10;
 
 //使用有参构造函数时,将ArrayList初始化为EMPTY_ELEMENTDATA,空数组指向它
 private static final Object[] EMPTY_ELEMENTDATA = {}; 
   	 
 //无参构造所创建的实例,将ArrayList 初始化为空 	 
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	//这个是手动设置初始容量,在你清楚列表的大小时很有必要,因为自动扩容的开销非常大。
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }
	
    public boolean add(E e) {
    	
    	//看看前文的fist-fail 
    	//判断是否需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!    
        elementData[size++] = e;
        return true;
    }
	
    private void ensureCapacityInternal(int minCapacity) {
    
    //如果是空数组,就取最小要求的存储容量与默认容量的最大值
    
        if (elementData == DEFAULTCAPACITY_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);
    }
	//
    private static int hugeCapacity(int minCapacity) {
    //这里我没看懂,为什么最低要求的容量小于0,他就报异常,大佬可以在评论里告诉我下??
    
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

总结

  我觉得最重要的是扩容这部分了。当是无参构造实例的ArrayList时,先是复制一个空数组给它,当执行添加时才会划分一个内存为10的空间。
  ArrayList的储存范围是Integer.MAX_VALUE

 若有错误,请指出,谢谢了。
 继续,加油!!![2019/8/7]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值