zoukankan      html  css  js  c++  java
  • 解析集合 一 (重温ArrayList源码)

    (#)背景:最近遇到了很多集合层面的问题,可能是自己对于集合本身只是简单了解内部的原理,忽略了其中的细节,所以最近来再重温一下各种集合的实现细节

    (#)原理:对于ArrayList首先,应该知道就是这是一个底层用‘动态数组’实现的集合,此类继承的接口不多说了,这个没什么实际的意义,下面一起来看看内部实现代码

    这是此类的成员变量,很容易理解,默认的数组大小10,定义控的数组实例,很显然elementData这个数据就是存储list中的元素的可变数组,注意此数组是不可序列化的,

    size这个就是代表数组中实际存储的元素的数量.

    (#)下面看看实例化一个List的时候,内部是怎么实现的----构造方法

    ArrayList提供了三个构造方法,当不指定大小的时候,默认的情况会创建一个空的数组,当实际存在一个元素的时候,数组会进行一次扩容,大小会变成默认大小也就是10,

    当指定大小的时候,会创建一个initialCapacity大小的数组来初始化,当传入一个集合的时候,如果集合空那么还是创建一个空的集合,否则会将传入集合的元素copy到ele

    mentData中,此时完成了对与内部数组的初始化

    (#)一直再说ArrayList是动态数组,那么这个动态是怎么体现的呢,下面来看一下

    每次添加元素的时候,都会进行检查,来确定是否需要进行扩容,当存入的元素加上size已经大于elementData的时候,此时需要进行扩容了,可以中带关注一下grow

    函数,此函数是进行扩容的核心代码,扩容的时候会先进行一个1.5倍的扩容,然后与实际需要的大小进行比较,进行一个最后大小的确认,之后剩下的就很简单了,将原有

    数组的内容copy过去就可以了,现在elementData就变成了扩容之后的数组了

    (#)下面来看看,增删改查了

    查询代码也是很简单的,遍历集合来查找指定的元素,但是一个问题就是查询的效率不太高,看代码也看到了,最坏的情况需要遍历O(n)次,而这种get(i),速度就很快了

    相当于直接elementData[i],所以是O(1)的,set方法与之类似,需要记得一点就是所有涉及到下表i的操作,都需要进行越界检查,越界检查只需要和size比较就可以了

    而不是与elementData.size比较

    对于add方法,可以看出来这是一个核心方法,添加元素的时候,首先需要做的就是判断是否需要进行扩容,所以将size加1进行此次判断,扩容这步过后才是存储数据,

    对于删除方法的话,稍微复杂一点点,首先还是会进行越界检查,之后修改了modCount,这个字段非常有用,它记录了数组的修改次数,有一些集合在遍历的时候要进行

    modCount与expectedModCount的比较,如果只修改了其中一个就会抛异常了ConcurrentModificationException,这个以后再说,剩下的删除就很简单了,直接把

    index后的通过复制向前移动一位,然后将最后一个直接设置成null,整体上使用了一个比较巧妙的方法来进行删除,其实我觉得设置成null与// clear to let GC do its work

    关系不大,因为如果你不设置成null的时候,那么末尾就会存在两个一样的元素........

    (#)iterator的实现, 这个是比较有意思的,也是大师的设计,废话不多说,来一起看看

    在调用iterator的时候,实际上等于每次都是new 了一个Itr类,下面看看这个内部类的代码

    cursor就相当于一个游标,来标记elementData的下一个元素,你看这里就有一个问题来了,每次next的时候,都会比较modCount和expectedModCount。。。。

    就像上面说的如果在正在遍历的时候修改了elementData那么modCount就会改变,这个时候就会抛异常了,而使用Itr自带的remove方法来删除的话,不会抛异常,

    原因就是此remove方法同时维护了modCount和expectedModCount,还有一个问题需要关注的就是,每次调用iterator()方法的时候,每次都会新new一个迭代器

    出来,这在业务上也是合理的,因为迭代器只能便利一次嘛,如果每次不new一个新的出来,那么只能迭代一次了,剩下的方法其实都是基本方法的变形,理解了所有基本

    的操作之后,我想没有其他问题想不明白的了

    (#结尾)当对于某部分代码有疑问,想不明白的时候,最简单的办法其实就是看看源码,不仅能学习别人的代码风格,设计思路,还能熟悉原理,这样才能写出来更优雅的代

  • 相关阅读:
    Leetcode NO.110 Balanced Binary Tree 平衡二叉树
    Leetcode NO.226 Invert Binary Tree 翻转二叉树
    Leetcode NO.215 Kth Largest Element In An Array 数组中的第K个最大元素
    根据特征的浏览器判断
    Cygwin在打开在当前目录
    【转帖】科学对待 健康养猫 打造快乐孕妇
    解决chrome浏览器安装扩展、应用程序一直处在“检查中”的问题
    对【SQL SERVER 分布式事务解决方案】的心得补充
    关于“点击这里继续访问您选择的百度XXX”
    VBA一例:如何保持文本框焦点
  • 原文地址:https://www.cnblogs.com/wscit/p/6635465.html
Copyright © 2011-2022 走看看