ArrayList学习小结

     看了java里ArrayList类的部分源码,做个小结。

     变量:

                  transient Object[] elementData;   //存放数据的数组,transient表示这个变量不能被序列化(我也不太懂)
                  private int size;                                 //当前存放元素的数量

      常量(都为private):

                  int DEFAULT_CAPACITY = 10                                                           //初始化默认容量
                 Object[] EMPTY_ELEMENTDATA = {};                                              //如果指定初始容量为0,那elementData就指向这个
                 Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};       //如果指定初始容量不为0,那elementData就指向这个。
                 int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;                          //数组允许最大容量,add方法里有讲解

      构造方法:

          如果是默认构造ArrayList,size=DEFAULT_CAPACITY,初始化后,加入第一个元素之前,私有成员elementData指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA,大小为0。这样做应该是为了节省空间。
               而指定大小的的构造,elementData直接初始化为指定大小的数组。

      方法:

   1、 给定一个对象,在list中找这个对象,如indexOf,contains方法,实际上是调用了对象的equals方法。给定的对象可以是null。

   2、调用add或类似方法时,要检查是否需要扩容。以add(E e)方法为例:

                    当ArrayList已经有元素时,取size+1作为最小容量,如果最小容量比elementData的length大,那就需要扩容了。扩容,把length和length>>1(length右移一位)相加得到新容量,如果新容量还是比最小容量小,那新容量就等于最小容量。
                   现在要检查新容量是否超过了允许最大容量(就是MAX_ARRAY_SIZE),如果超过了,就再比较最小容量和允许最大容量,还是超过,那就取Integer.MAX_VALUE;没超过,就取允许最大容量。
                  最后新建一个新容量数组,把原elementData的元素复制过去,替换elementData。

                 注意 因为有默认构造这个例外,要先检查elementData是否初始化空,若是则取size+1和默认构造容量的较大值作为最小容量。感觉一般取的都是默认构造容量。

                再来看一下MAX_ARRAY_SIZE,源文件里的解释是因为保留了一些数组头部的数据,所以要减8。
                还有一个细节,在add时,modCount会自增,modCount是AbstractList里的变量,Arraylist继承AbstractList,那modCount是啥?这涉及到迭代器,简单来说,迭代器开始时会把modCount保留一个副本,在迭代过程中,如果发现modCount和副本不一致,说明set、add、remove等方法在这期间被调用了,数组被修改了,那就会抛出异常ConcurrentModificationException。这就是所说的ArrayList是非线程安全的,通过这样来保证遍历时的正确性。
     3、 remove方法  先检查是否越界,移除的如果不是最后一个,就把index后面的元素前移一个单位。然后,最后一个位置指向null,释放内存。

     4、对数组的操作,如复制、移动元素,用的方法基本为native,也就是调用了非java代码,如C、C++。

     5、遍历器 iterator:

                 成员:

                int cursor;           //指向元素下标  
                int lastRet = -1;     //上一个返回的元素,-1表示没有
                int expectedModCount = modCount;     //用于安全 

               方法:

              public boolean hasNext(): 检查cursor是否越界

              public E next():先会检查是否越界,不越界时返回cursor指向的元素,lastRet的值为cursor的值,最后cursor加1

               public void remove():  先会检查lastRet是否小于0,若小于0则说明没有返回元素,会抛出异常。若大于等于0,则调用arrayList的remove方法,以lastRet作为参数;之后                           cursor的值赋为lastRet,lastRet变为-1。
                          说明应该在调用next方法之后,再调用remove方法      

      ListIterator:

            与iterator比较类似,可正序、逆序遍历,可删除、替换元素,可得前一个、后一个下标

       SubList:
                  SubList是一个类,继承自AbstractList,有get、set、add等方法,与arrayList类似。要注意操作subList对象实际上是对父arrayList进行操作,对subList的改变会影响到arrayList

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值