h2 { background-color: Skyblue }

AbstractCollection认识

  AbstractCollection是Collection接口的抽象实现。实现了一部分Colleciton,并且添加了几个新的方法。

源码之前的预热

  在进行AbstractCollection源码阅读前,先看看AbstractCollection中使用到的一些其他源码

  •      System.arraycopy(Object src,  int  srcPos, Object dest, int destPos,int length);
  •    Arrays.copyOf(T[] original, int newLength)

  1. System.arraycopy是Native方法,是java的本地方法,是用其他语言写的。所以我们是看不到更底层的代码的。但是native方法一般会比你自己写的效率更好。这个方法的作用是从src中复制(srcPos位置到srcPos+length-1位置)的元素到dest的destPos到destPos+length-1的位置。

  System.arraycopy(Object src,  int  srcPos, Object dest, int destPos,int length);

  src: source 代表源数组

  srcPos: source position 代表源数组起始的位置

  dest:  destination 代表目标数组。

      destpos: destination position 目标数组的起始位置

  length: length 复制的元素个数

  src和dest可以是同一个数组

 public static native void arraycopy(Object src,  int  srcPos,
                                      Object dest, int destPos,
                                      int length);

  2.Arrays.copyOf(T[] original, int newLength) 

     Arrays.copyOf(U[] original, int newLength, Class<? extends T[]> newType) 

     这个方法返回一个T[].

   original: 被复制的数组

   newLength: 返回的新的数组的长度

         newType: 返回的数组的类型(比如说String[]的数组还是Integer[]的数组),注意所有的数组的父类都是Object[]。

    @SuppressWarnings("unchecked")
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

   public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] // newtype如果是Object类型的话就创建一个Object[]的数组
            : (T[]) Array.newInstance(newType.getComponentType(), newLength); //否则就创建一个特定类型的数组, newInstance是native方法创建一个具体类型的数组
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength)); //然后把源数组移动到目标数组中.
        return copy;
    }

 源码分析

  1.类的声明,实现了Collection接口

public abstract class AbstractCollection<E> implements Collection<E> {}

  2.构造器方法

  protected AbstractCollection() {}    //protected 修饰说明只对子类或者同一个包下类可见

  3. 抽象方法

  public abstract Iterator<E> iterator(); 抽象方法未实现

public abstract int size();  抽象方法未实现

  4. 判断是否为空

  public boolean isEmpty() {  //通过判断size是否等于0判断这个容器是否为空
    return size() == 0;
  }

     5. 判断是否包含某个元素

  public boolean contains(Object o) { 
    Iterator<E> it = iterator();   //得到一个迭代器
    if (o==null) {                       //如果传进来是null就通过迭代器一个个对比是否是null,是null的话就返回true
    while (it.hasNext())
    if (it.next()==null)
    return true;
    } else {                              //如果传进来不是null就通过迭代器使用equals方法比较
    while (it.hasNext())
    if (o.equals(it.next()))      //如果equals方法比较true,则返回true
    return true;
    }
  return false;                      //没有相等的情况返回false
  }

  6. 通过容器的迭代器返回一个Object数组

  public Object[] toArray() {
    Object[] r = new Object[size()];  
    Iterator<E> it = iterator();
    for (int i = 0; i < r.length; i++) {
      if (! it.hasNext())        // fewer elements than expected 比预期的元素个数少的话就通过 Arrays.copyOf生成一个个数正好相等的Object数组
      return Arrays.copyOf(r, i);
      r[i] = it.next();        //把迭代器中的元素的引用赋值给数组
    }
  return it.hasNext() ? finishToArray(r, it) : r;   //迭代器元素个数比size的话,返回finishToArray(r, it), 否则直接返回对象。
  }

  7. 迭代器中的剩余的元素全部放入数组中

  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; MAX_ARRAY_SIZE;  //是最大的数组容量

  @SuppressWarnings("unchecked")
  private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
    int i = r.length;
    while (it.hasNext()) {
      int cap = r.length;
      if (i == cap) {                                        //如果容量满了就扩容
        int newCap = cap + (cap >> 1) + 1;  //每次容量增加2分之一
        if (newCap - MAX_ARRAY_SIZE > 0) // 能自动感知到容量是否超出了虚拟机允许的数组的容量,
          newCap = hugeCapacity(cap + 1); 
        r = Arrays.copyOf(r, newCap);       //r赋值成新的对象数组对象,这个对象的大小是newCap(new Capacity)
      }
    r[i++] = (T)it.next();  //i自增,并且赋值新的元素
  }
  // trim if overallocated   如果数组容量有余的话,就把数组修剪成正好的容量
  return (i == r.length) ? r : Arrays.copyOf(r, i);
  }

  //重新给一个大小因为cap + (cap >> 1) + 1可能会超过int的最大值,或者超过数组的长度的最大值

  private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
    throw new OutOfMemoryError
    ("Required array size too large");
    return (minCapacity > MAX_ARRAY_SIZE) ?
    Integer.MAX_VALUE :
    MAX_ARRAY_SIZE;
  }

  8.add方法,不支持add方法

  public boolean add(E e) {
    throw new UnsupportedOperationException();
  }

  9 移除一个元素

public boolean remove(Object o) { 
  Iterator<E> it = iterator();
  if (o==null) {                         //null的话通过判断是不是null是的话直接返回true
    while (it.hasNext()) {
      if (it.next()==null) {
      it.remove();
      return true;
      }
    }
  } else {
    while (it.hasNext()) {             //遍历迭代器
      if (o.equals(it.next())) {   //如果有对象相等的话就返回
      it.remove();                      //并且通过迭代器来消除对象 (迭代器不一定实现了消除,比如可能迭代器的消除会抛出一个UnsupportedOperationException())
      return true;
      }
    }
  }
return false;
}

   10. 是否包含所有的传入参数中的元素

public boolean containsAll(Collection<?> c) {
  for (Object e : c)
    if (!contains(e))    //只要有一个没有包含就直接返回false
    return false;
return true;
}

11.增加所有的元素到容器中

public boolean addAll(Collection<? extends E> c) {
  boolean modified = false;  //modified 代表是否修改过元素
    for (E e : c)         //遍历参数容器,add方法加入容器
      if (add(e))
        modified = true;
  return modified;
}

   12.移除全部

public boolean removeAll(Collection<?> c) {
  Objects.requireNonNull(c);            //C是null的话就抛出异常
  boolean modified = false;
  Iterator<?> it = iterator();
  while (it.hasNext()) {
    if (c.contains(it.next())) {       //遍历c容器,如果c包含一个元素,就把那个元素给remove掉
    it.remove();
    modified = true;
    }
  }
  return modified;
}

13.移除全部元素

public void clear() {
  Iterator<E> it = iterator();
  while (it.hasNext()) {
    it.next();
    it.remove();     //迭代器一个一个消除
  }
}

14. toString方法

public String toString() {
  Iterator<E> it = iterator();    //如果没有包含元素返回[]
  if (! it.hasNext())
  return "[]";

  StringBuilder sb = new StringBuilder();
  sb.append('[');
  for (;;) {             
    E e = it.next();
    sb.append(e == this ? "(this Collection)" : e);   //e == this 用来防止死循环
    if (! it.hasNext())
      return sb.append(']').toString();
    sb.append(',').append(' ');
  }
}

总结:AbstractCollection只是给其他类使用的一个模板,要成为一个能够工作的容器还需要很多方法和存储的元素对象。

彻底理解容器类(2)------- AbstractCollection深入了解的更多相关文章

  1. Java编程的逻辑 (52) - 抽象容器类

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  2. 走进Java中的持有对象(容器类)之一 容器分类

    Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类. 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 ...

  3. Java中的泛型 (上) - 基本概念和原理

    本节我们主要来介绍泛型的基本概念和原理 后续章节我们会介绍各种容器类,容器类可以说是日常程序开发中天天用到的,没有容器类,难以想象能开发什么真正有用的程序.而容器类是基于泛型的,不理解泛型,我们就难以 ...

  4. setAction方法 Snackbar 右侧按钮可以被点击并处理一些事件

    从数据库同一记录取得的字段所组装成的对象应该是同一个对象,然后由不同的Session从数据库同一条记录上分别取得对象,它们的内存地址是不一样的. 一般来说,常见的数字加密方式都可以分为两类,即对称加密 ...

  5. 黑马程序员:3分钟带你读懂C/C++学习路线

    随着互联网及互联网+深入蓬勃的发展,经过40余年的时间洗礼,C/C++俨然已成为一门贵族语言,出色的性能使之成为高级语言中的性能王者.而在今天,它又扮演着什么样重要的角色呢?请往下看: 后端服务器,移 ...

  6. 【转】Java基础——容器分类

    Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类. 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 ...

  7. Java编程的逻辑 (35) - 泛型 (上) - 基本概念和原理

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  8. C++学习路线(转载)

    随着互联网及互联网+深入蓬勃的发展,经过40余年的时间洗礼,C/C++俨然已成为一门贵族语言,出色的性能使之成为高级语言中的性能王者.而在今天,它又扮演着什么样重要的角色呢?请往下看: 后端服务器,移 ...

  9. 8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语

    有效地利用已有的成果,将经典的.优秀的算法标准化.模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想. c++语言提供的标准模板库( ...

随机推荐

  1. Linux 6.4 partprobe出现warning问题

    今天在给服务器做LVM的时候(服务器的系统是CentOS 6.3),用fdisk分区之后,用w写入分区表的时候,就提示Command (m for help): wThe partition tabl ...

  2. windows下搭建Nexus3私服和基于IDEA15的Maven学习笔记

    搭建Nexus私服. 首先去官网下载window下用的zip文件.https://www.sonatype.com/download-oss-sonatype. 解压之后包含下面两个文件 进入nexu ...

  3. 游戏UI框架设计(二) : 最简版本设计

    游戏UI框架设计(二) --最简版本设计 为降低难度决定先讲解一个最简版本,阐述UI框架的核心设计理念.这里先定义三个核心功能: 1:UI窗体的自动加载功能. 2:缓存UI窗体. 3:窗体生命周期(状 ...

  4. Debug和Release区别

    VC下Debug和Release区别 最近写代码过程中,发现 Debug 下运行正常,Release 下就会出现问题,百思不得其解,而Release 下又无法进行调试,于是只能采用printf方式逐步 ...

  5. java初级开发程序员(第三单元)

    1.if基本选择结构: 语法: if(条件){     //程序执行时,先判断条件.当结果为true(真)时,程序先执行大括号的代码块,再执行if结构(即{}部分)后面的代码.当结果为false(假) ...

  6. Ant学习总结3(很多的属性,用的时候方便查找)

    感谢原作者:http://blog.csdn.net/lipeijs3/article/details/5137160 一.              Ant 与 Makefile : GNU Mak ...

  7. 自动化测试 -- 通过Cookie跳过登录验证码

    之前写过一篇博客:自动化测试如何解决验证码的问题. http://www.cnblogs.com/fnng/p/3606934.html 介绍了验证码的几种处理方式,最后一种就是通过Cookie跳转过 ...

  8. 谈 jquery中.band() .live() .delegate() .on()的区别

    bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数 $("a").bind("click",function(){alert(& ...

  9. Spring 数据源

    1.使用org.springframework.jdbc.datasource.DriverManagerDataSource说明:DriverManagerDataSource建立连接是只要有连接就 ...

  10. .Net程序员学用Oracle系列(19):我知道的导出和导入

    1.传统的导出/导入工具 1.1.EXP 命令详解 1.2.IMP 命令详解 1.3.EXP/IMP 使用技巧 2.新的导出/导入工具 2.1.EXPDP/IMPDP 参数说明 2.2.EXPDP/I ...