java集合类源码详解-ArrayList(5)-基于JDK8

上次,测试了java集合类支持遍历方式的效率比较,今天再通过断电调试,去ArrayList底层的迭代器做了什么。

首先在迭代器这里打上断电,(在实际中变量ArrayList最后别用迭代器,因为他很慢)

可以看到这个iterator()方法返回值是一个迭代器,函数体是return new Itr()

点击下一步。可以看到Itr是一个ArrayList里面的一个类,从右边类结构图可以看到。ArrayList里面有四个类。

ArrayList的父类abstractList里面也有Itr这个类。

这里先点开Itr这个类,里面有哪些方法。

 再次点击下一步。类成员初始化。

再次点击下一步。回到return语句。

 再次点击下一步,返回到我们自己写的代码里面,开始执行hasnext()方法。

这里再点击下一步,进入hasnext()方法。这个方法是判断是否还有下一个元素

这里return语句 cursor是下一个元素返回的索引,size是容器的大小。

这里肯定不等于。返回true。

点击下一步,开始执行next()方法。

再次点击下一步,进入next()方法,这个方法是Itr内部的一个方法。这里先会去执行checkForComodficaation()这个方法,

这个方法主要是检查在迭代时,要迭代的容器的数量是否发生变化,如果发生变化,就抛异常

 点击下一步,这里不会抛异常

 再次点击下一步,把下一个元素索引0,赋值给当前元素的索引i,此时i为0.

点击下一步,此时判断索引是否大于等于了容器的大小,这里肯定没有。

 再次点击下一步。这里会创建一个数组引用当前数组,然后再次判断下标 i 是否大于等于数组长度。

为什么要这样呢?因为这个新的element数组,是引用的之前我们的10万大小的数组,如果在迭代过程中增加了元素,下标 i 会增加,因为数据增加了,数据在数组里面对应是有下标的,也要多,那么肯定会比之前没增加数据的数据最大长度大或者相等。

如果出现这种情况,说明在迭代过程中,我们向容器里面添加元素,所以抛出异常。

再次点击下一步。到这一步,马上我们就能return要遍历的第一个元素了,所以为下一次遍历做准备

cursor+1

 再次点击下一步,我们这里返回第一个元素,借助lastRet这个变量,这个变量初始值是最后一个变量索引,值为-1,

我们把当前要遍历的索引赋给它,然后返回这个数组即 elementData[0] 这样就完成了第一个元素的访问。

好了,ArrayList的迭代器方法和内部一个Itr类源码跟踪就结束了,下面再来看看get()这个方法,同样 打上一个可爱的断点。

点击下一步。get()方法是返回指定位置上的元素,从0开始,这里可以清晰看到get()方法,比 之前的next()方法简单多了,内部没那么多东西。

再次点击下一步,执行范围检查函数。如果索引大于等于了容量的实际存储的数据数量

比如一个长度为10的数组,里面有10个数 分别是1到10,此时的size是10,那么索引位9是最大的,index=9当然可以

但是index>=10,是绝对不可以的。或者数组里面只有1到5,此时size=5,数组最大容量为10,你获取index=4当然可以,但是获取index=5,此时这个位置是没有数的,所以会抛异常。

 再次点击下一步,卧槽,此时不是应该返回一个element[index]么,这是什么!为什么还传个索引过去?

当我们再次点击下一步,会发现这是一个方法。此时的E是student,

这个方法其实就是返回一个强转的student类型的element[index]数组。

这里可以看出这个操作的封装力度很强,连强转都要封装。

好了,到此为止,就告一段落了。

后续楼主会继续学习集合类的源码,另外博客什么地方写错,请指出,大家一起学习进步!!   

猜你喜欢

转载自blog.csdn.net/qq_37889257/article/details/84335299