JavaSE基础知识(二十一)--Java集合(容器)之类ArrayList的源码分析(二)

Java SE 是什么,包括哪些内容(二十一)?

本文内容参考自Java8标准
再次感谢Java编程思想对本文的启发!
①、batchRemove(Collection<?> c, boolean complement)

    //private方法,支撑类内部的public方法
    //返回类型为boolean,带一个Collection<?>类型的形式参数c
    //和一个boolean类型的形式参数complement
    //它的作用是:处理当前列表与某个集合元素之间的删除与保留。
    private boolean batchRemove(Collection<?> c, boolean complement) {
       //将当前列表存储元素的数组对象赋值给另一个引用elementData
       //新的引用elementData是final的
       final Object[] elementData = this.elementData;
       //定义两个int类型的变量r,w,初始化都为0
       int r = 0, w = 0;
       //定义一个boolean类型的变量modified,初始化为false
       boolean modified = false;
       //try...catch块,捕捉异常机制
       try {
          //for循环
          for (; r < size; r++)
             //如果c.contains(elementData[r]返回的值与complement相等
             //(complement为true表示包含,未false表示不包含)
             if (c.contains(elementData[r]) == complement)
                //则将当前元素elementData[r]替换elementData的第一个元素.
                //以此类推。这个时候w的值为0表示第一个元素,w还会自增。
                elementData[w++] = elementData[r];
                //当前循环完毕后,数组elementData中的元素都是
                //c.contains(elementData[r]) == complement成立的元素.
           //这里再详细解释下这个for循环的思路:首先循环当前列表的数组element
           //中的每个元素.看表达式c.contains(elementData[r]) == complement
           //是否成立。如果成立则将当前元素替换element的第一个元素,同时用变量w
           //记录替换的次数,以此类推,直至整个数组循环完毕。
           //此时,数组element的前w个元素都是符合要求的元素。
       //finally语句,表示最后都会得到执行
       } finally {
          //即使c.contains(Object o)方法抛出异常,
          //仍保留与AbstractCollection的行为兼容性。
          //如果循环正常完成,r的值就会等于size
          //这里判断r值不等于size的情况
          if (r != size) {
             //数组的创建和元素的复制
             System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
             //w的值重新计算
             w += size - r;
          }
          //如果w不等于size的值
          //只有整个数组的元素都在指定集合c中才会出现这种情况
          if (w != size) {
             //清空数组索引值大于w的元素,仅保留比对成功的元素。
             for (int i = w; i < size; i++)
                //将数组的元素设置为null。
                elementData[i] = null;
             //累加数组结构性修改的次数
             modCount += size - w;
             //将数组的元素个数赋值给size
             size = w;
             //修改变量modified的值
             modified = true;
          }
       }
       //返回变量modified的值
       return modified;
    }

②、writeObject(java.io.ObjectOutputStream s)

    //private方法,支撑类内部的public方法
    //返回类型为void,带一个java.io.ObjectOutputStream类型的形式参数s
    //抛出IOException异常
    //它的作用是:将当前列表对象实例的状态保存到流(即,对其进行序列化)。
    //ArrayList重写了类Object中的方法writeObject(java.io.ObjectOutputStream s)
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        //将modCount的值赋值给变量expectedModCount保存
        int expectedModCount = modCount;
        //调用变量s的方法defaultWriteObject(),序列化一些隐藏的内容
        //这一步是将类ArrayList中除了transient修饰的其他变量进行序列化
        s.defaultWriteObject();
        //调用变量s的方法writeInt(size),将size作为实际参数传入。
        s.writeInt(size);
        //for循环
        for (int i=0; i<size; i++) {
           //调用变量s的方法writeObject(Object o)。
           //将数组的每个元素elementData[i]作为实际参数传入。
           s.writeObject(elementData[i]);
        }
        //快速失败机制,如果在这个期间数组有结构性的修改
        //也就是modCount != expectedModCount
        if (modCount != expectedModCount) {
           //抛出ConcurrentModificationException()异常。
           throw new ConcurrentModificationException();
        }
    }

③、readObject(java.io.ObjectInputStream s)

    //private方法,支撑类内部的public方法
    //返回类型为void,带一个java.io.ObjectOutputStream类型的形式参数s
    //抛出IOException,ClassNotFoundException异常
    //它的作用是:从流中重构一个列表对象实例(即,对其进行反序列化)。
    //ArrayList重写了类Object中的方法readObject(java.io.ObjectOutputStream s)
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        //首先将elementData初始化为EMPTY_ELEMENTDATA
        elementData = EMPTY_ELEMENTDATA;
        //反序列化一些隐藏的内容。
        s.defaultReadObject();
        //反序列化int类型的内容
        //源码中备注的是ignored,表示这步可有可无
        //因为在接下来的for循环中是直接读取每个元素,全部读取完毕后自然就知道了size
        s.readInt(); 
        //如果size>0
        if (size > 0) {
            //根据size调用方法ensureCapacityInternal(int minCapacity)
            //创建一个新的数组
            ensureCapacityInternal(size);
            //将element赋值给Object[]类型的引用a
            Object[] a = elementData;
            //for循环
            for (int i=0; i<size; i++) {
               //反序列化每个元素
               a[i] = s.readObject();
            }
        }
    }

④、listIterator(int index)

    //public方法,供对象实例调用
    //返回类型为ListIterator<E>,带一个int类型的形式参数index
    //它的作用是:返回一个从当前列表指定索引位置index开始迭代元素的迭代器对象
    //这个迭代器设置了快速失败机制。
    public ListIterator<E> listIterator(int index) {
       //如果index的值小于0或者大于size
       if (index < 0 || index > size)
          //抛出IndexOutOfBoundsException异常
          throw new IndexOutOfBoundsException("Index: "+index);
       //返回一个内部类ListItr的对象实例.同时将index作为实际参数传入。
       return new ListItr(index);
    }

⑤、listIterator()

    //public方法,供对象实例调用
    //返回类型为ListIterator<E>,不带任何形式参数
    //它的作用是:返回一个从头开始迭代元素的迭代器对象
    //这个迭代器设置了快速失败机制。
    public ListIterator<E> listIterator() {
       //返回一个内部类ListItr的对象实例.同时将0作为实际参数传入。
       //0为数组第一个元素的索引位置
       return new ListItr(0);
    }

⑥、iterator()

    //public方法,供对象实例调用
    //返回类型为Iterator<E>,不带任何形式参数
    //它的作用是:返回当前列表对象的通用迭代器对象
    //Iterator是通用的迭代器类型
    //这个迭代器设置了快速失败机制。
    public Iterator<E> iterator() {
       //返回一个内部类Itr的对象实例
       return new Itr();
       //内部类Itr的源码在下一篇博文中有详细的描述。
    }

⑦、subList(int fromIndex, int toIndex)

    //public方法,供对象实例调用
    //返回类型为List<E>,带两个int类型的形式参数fromIndex和toIndex
    //它的作用是:根据指定索引值指定的范围返回当前列表的一个子列表
    //也可以成为返回当前列表的一个视图。
    //fromIndex(包含),toIndex(不含)
    public List<E> subList(int fromIndex, int toIndex) {
       //保证索引值fromIndex和toIndex的合法性
       subListRangeCheck(fromIndex, toIndex, size);
       //返回一个内部类SubList对象。
       //同时将当前列表对象this,0,fromIndex,toIndex作为实际参数传入。
       return new SubList(this, 0, fromIndex, toIndex);
    }

⑧、subListRangeCheck(int fromIndex, int toIndex, int size)

    //static方法,属于类,与对象实例无关
    //返回类型为void,带三个int类型的形式参数fromIndex,toIndex和size
    //它的作用是:保证索引值fromIndex和toIndex的合法性
    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
       //如果起始的索引值fromIndex小于0
       if (fromIndex < 0)
          //抛出IndexOutOfBoundsException异常
          throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
       //如果结束的索引值大于size
       if (toIndex > size)
          //抛出IndexOutOfBoundsException异常
          throw new IndexOutOfBoundsException("toIndex = " + toIndex);
       //如果起始的索引值大于结束的索引值
       if (fromIndex > toIndex)
          //抛出IllegalArgumentException异常
          throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + 
                                               ")");
    }

PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值