ArrayList源码解析

ArrayList源码解析

ArrayList的结构

ArryList是一个泛型类它继承了 AbstractList<E>,实现了RandomAccess、List、Cloneable, java.io.Serializable接口

因此它具有列表的添加、删除、查找、并且可以快速访问(通过下标)等功能。

在ArrayList的源码中我们可以看到

说明ArrayList底层是基于Object数组实现的。

而为了满足数组长度的动态变化,ArrayList还有很多关于ArrayList容量的函数

而常规的集合添加,删除,查询相关的函数这就不探讨了。比较简单

ArrayList扩容流程

下面我们以一个空ArrayList添加一个元素演示这个扩容流程

  1. 用无参构造方法创建出一个ArrayList

     ArrayList<Integer> list =new ArrayList<>();

    此时执行这样的代码:

       public ArrayList() {
             this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
         }

    将elementData数组 初始化为空数组 此时size = 0 数组元素数为0

  2. 执行add方法添加一个元素

     list.add(1)

    此时执行这样的代码

     public boolean add(E a) {
         ensureCapacityInternal(size + 1);//此时size + 1 = 1因为这里是第一次添加元素
         elementDate[size ++] = e;
         return true;
     }

  3. 进入ensureCapacityInternal方法中

     //只是调用2个方法
     private void ensureCapacityInternal(int minCapacity) { // minCapacity = 1
         ensureExplicitCapacity(calculateCapacity(elementData,minCapacity))
     }
     private static int calculateCapacity(Object[] elementData, int minCapacity) { // minCapacity = 1
         //当前集合是不是空数组
         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             //是,由于DEFAULT_CAPACITY = 10,minCapacity = 1
             //返回10
             return Math.max(DEFAULT_CAPACITY, minCapacity);
         }
         return minCapacity;
     }
     //再进入方法ensureExplicitCapacity
     private void ensureExplicitCapacity(int minCapacity) {
         //modCount做修改判断的
         modCount++;
         // overflow-conscious code
         //此时元素还未加入到elementData中 所以数组长度为0 进行扩容
         if (minCapacity - elementData.length > 0)
             //扩容的核心方法
             grow(minCapacity);
     }

  4. 核心扩容方法grow(int minCapacity)

     private void grow(int minCapacity) {
         int oldCapacity = elementData.length; //oldCapacity = 0
         int newCapacity = oldCapacity + (oldCapacity >> 1)// 扩容为old的1.5倍
         if(newCapacity - minCapacity < 0) {
             //不足
             newCapacity = minCapacity;
         }
         //是否超过规定长度 
         if (newCapacity - MAX_ARRAY_SIZE > 0)
                 newCapacity = hugeCapacity(minCapacity);
         //利用Arrays.copy对数组赋值。也就是说 数组的长度为newCapacity
         elementData = Arrays.copyOf(elementData, newCapacity);
     }

ArrayList的内部类

在看源码的途中的我还发现了

Itr、ListItr、SubList、ArrayListSplierator这几个内部类

Itr

Itr实现了迭代器接口,目的是为ArrayList提供迭代器的遍历方式,这就让我们可以使用foreach的形式来遍历

 ArrayList<Integer> list = new ArrayList<>();
 Iterator<Integer> = list.iterator();
 while(itr.hasNext()){
      System.out.println(itr.next());
 }

ListItr

ListItr也是为ArrayList提供了遍历方式,比如双向遍历和允许修改元素和添加元素(expectedModCount = modCount)

 ListIterator<String> listItr = list.listIterator();
 while (listItr.hasNext()) {
     System.out.println(listItr.next());
 }
 ​
 while (listItr.hasPrevious()) {
     System.out.println(listItr.previous());
 }

SubList

SubList是ArrayList的子列表实现,调用subList(int fromIndex, int toIndex)会返回一个SubList实例,这个子列表视图可以对原列表的部分进行操作,而不会创建 新的列表

 //[A,B,C,D]
 List<String> subList = list.subList(1, 3);
 System.out.println(subList); // 输出: [B, C]
 ​
 subList.set(0, "E");
 System.out.println(list); // 输出: [A, E, C, D]

ArrayListSplierator

基本介绍

Splierator是Java8引入的一种新的迭代器,用于并行遍历和分割集合中的元素,ArrayListSplierator是它的实现类

trySplit(): 将当前 Spliterator 拆分成两个 Spliterator,返回一个新的 Spliterator 处理一部分元素,保留原来的 Spliterator 处理剩下的部分。这个方法在并行流处理中非常重要,可以实现数据的分治处理。

tryAdvance(Consumer<? super T> action): 如果还有剩余元素,处理当前元素并返回 true,否则返回 false。这个方法用于顺序处理元素。

forEachRemaining(Consumer<? super T> action): 对剩余的每个元素执行给定的操作,直到处理完所有元素或出现错误。这个方法用于处理剩余的所有元素。

estimateSize(): 返回 Spliterator 中剩余元素的估计大小。

characteristics(): 返回 Spliterator 的特性,比如 ORDEREDDISTINCTSORTEDSIZEDNONNULLIMMUTABLECONCURRENTSUBSIZED 等。

挖掘

下面我们来使用下spliterator

 ArrayList<Integer> objects = new ArrayList<>();
 objects.spliterator().forEachRemaining(System.out::println);

我发现这和stream流的形式不是很像吗?

  
objects.stream().forEach(System.out::println);

然后我就点进这个stream中发现

然后经过调试发现

所以我们可以认为ArrayList中的这个spliterator就是为stream提供支撑的。

并且stream().parallel()串行流,它不也是和这个Splierator用于并行遍历和分割集合中的元素的理念相符合

当然如果看过stream流的源码应该是知道,不过我没看过,所以就觉得很有意思,感觉东西都串起来了

参考:ArrayList 源码分析 | JavaGuide

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值