一点一点看JDK源码(一)Collection体系概览

liuyuhang原创,未经允许进制转载

本文举例使用的是JDK8的API

目录:一点一点看JDK源码(〇)

1.综述

  Collection为集合类,是jdk中最为常用的类了,实际上我并不认同这个东西叫做集合

  我更倾向于叫做容器,当然容器不止有它一种。

  在计算机专业中,大概都会学一门叫做《数据结构》的课程吧

  本质上来说,数据结构,实际上是设计一种容器,而容器的特性大体包括如下:

  • 容器中如何进行存储
  • 容器中的数据如何获取
  • 容器中的数据如何添加  
  • 容器中的数据如何遍历
  • 器中的数据如何搜索
  • 容器中的其他特性(判空,替换,排序,溢出,并发,同步,拆分,汇聚等等)

  在我的眼中,Collection是容器的框架集,其中包含了我们经常使用的容器,

  

2.Collection的关注点

  Collection隶属于java.util包。在本文中不讨论concurrent包或其他派生集合体系,只讨论基础

  从Collection类的原码类注释@see中可看到,集合体系的大概设计中重点关注的如下:

  • Set(接口)
  • List(接口)
  • Map(接口)
  • SortedSet(接口)
  • SortedMap(接口)
  • HashSet(类)
  • TreeSet(类)
  • ArrayList(类)
  • LinkedList(类)
  • Vector(类)
  • Collections(类)
  • Arrays(类)
  • AbstractCollection(抽象类)

  之所以只关注这些,主要有两方面原因:

    ①我们的时间和技术水平有限,不可能完整的看完JDK

    ②JDK中的任何设计都是迭代产生的,我们没有必要看旧版本而不更新的类

  接下来将依照上述内容,从接口底层给它从头扒到尾,虽然说Collection中@see的是这些

  但是关注点肯定不止于此。

3.Collection剖析

  先上Collection源码,去掉原doc注释,我想写的内容直接写在贴出来的代码中作为注释了。

 public interface Collection<E> extends Iterable<E> {
// Query Operations 原注释,不明意义 //定义size方法,应返回size大小,最大值为Integer.MAX_VALUE
int size(); //定义isEmpty方法,用于返回是否为空
boolean isEmpty(); //定义contains方法,判断一个obj是否属于此集合
boolean contains(Object o); //定义迭代器方法,返回一个迭代器对象
Iterator<E> iterator(); //定义转换为转换Obj数组的方法,返回一个obj数组
Object[] toArray(); //定义转换为泛型T数组的方法,返回一个指定泛型的数组
<T> T[] toArray(T[] a); //定义add方法,添加一个元素e,并返回添加成功标志
boolean add(E e); //定义remove方法,移除一个元素obj,并返回移除元素成功标志
boolean remove(Object o); //定义containsAll方法,判断是否包含集合实例对象c
boolean containsAll(Collection<?> c); //定义addAll方法,添加集合实例对象c到本实例中
boolean addAll(Collection<? extends E> c); //定义removeAll方法,从本实例中移除集合实力对象c
boolean removeAll(Collection<?> c); /**
* jdk8新增
* 大意为:
* 定义removeIf方法,该方传递参数为函数式,传递内容是一个接口类型,该接口类型
* 定义为一个filter函数,该函数用于传递给Objects.requireNonNull判断,然后调用
* 迭代器,将满足该定义的filter的本实例中的元素移除
* @since 1.8
*/
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
} //定义retainAll方法,取本例与集合实例c的交集,判断交集元素数量是否大于0
boolean retainAll(Collection<?> c); //定义clear方法,清除本例集合中的所有元素
void clear(); // Comparison and hashing 原注释,不明意义 //不解释
boolean equals(Object o); //定义hashCode方法,获取hashCode标记的方法
int hashCode(); /**
*jdk8新增
*大意为:
*将迭代器拆分,重写自Iterable接口,从已知元素数量的本例中返回拆分后的迭代器
*此方法返回的为本类本身
*子类可能重写迭代器拆分,将一个集合的迭代拆分为多个集合的迭代交由多个线程
* @since 1.8
*/
@Override//重写父类
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
} /**
* jdk8新增
* 大意为:
* 将默认的迭代器拆分后的结果,聚合为流,该流并非io中的流,
* 是一种类似于数据排序操作流
* @since 1.8
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
} /**
* jdk8新增
* 同上,但是具体其他的实现中,因为可并行,所以可能是线程不安全的
*
* @since 1.8
*/
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}

  以上代码对Collection接口中的方法进行了简单的解释,同时对java8新增的一些方法也进行了简单的解释。

  因为定义的都是接口,实际实现的方法非常的少,

  而应java8多线程的特性提供的一些default方法也有子类去实现。

  在堆Collection接口中的源码进行了解的同时,不要忘记此接口继承了Iterable接口。

  因此Iterable接口也必定要看一下的,内容比较少,但是通过源码的剖析,发现了集合类的共性:

  集合作为容器,其体系中的所有集合都包括了:

  大小(size),判空(isEmpty),添加元素(add),删除元素(remove),是否包含(contains)

  转换数组(toArray),清空(clear),遍历与迭代(forEach(父接口中),iterator)

  是否相同(equals),哈希(hashCode),求交集(retainAll)

  除此之外,提供了java8的分离接口,聚合接口,为了大容量集合的多线程操作

  注意,Collection接口并没有重写父接口的forEach方法,而iterator方法虽然有出现,但是没有@Override注解

  同样贴一下代码,同样的去掉原doc注释,我想写的内容直接写在贴出来的代码中作为注释了。

 public interface Iterable<T> {

     //定义iterator方法,返回迭代器
Iterator<T> iterator(); /**
* jdk8新增
* 大意为:
* 根据action调用Objects.requireNonNull进行过滤
* 过滤结果调用for循环取出,
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
} /**
* jdk8新增
* 大意为:
* 分离迭代器,将未知大小的迭代器进行拆分,返回拆分的迭代器本身
*
* @since 1.8
*/
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}

有时候我们并不怎么关心父接口的问题,但是实际上这个问题有点重要的还是,上两张图解释一下:

 不要以为以上两种接口定义实现类的方式没区别,实际上有区别,区别大了,可实现的方法列表有差异

该问题具体解析,将在后续更新中详细写代码测试。

Collection接口内容较少,多数都只是定义了必要内容,具体实现较少。难点都在java8中的default方法上了

等以后弄彻底明白了可能再写通俗解释和常用方式。

明天更对于List接口的剖析和ArrayList的简要剖析!

以上!

一点一点看JDK源码(一)Collection体系概览的更多相关文章

  1. 一点一点看JDK源码(〇)

    一点一点看JDK源码(〇) liuyuhang原创,未经允许进制转载 写在前面: 几乎所有的大神都会强调看源码,也强调源码的重要性: 但是如何看源码,源码看什么?看了什么用?看了怎么用? 困扰很多人, ...

  2. 一点一点看JDK源码(二)java.util.List

    一点一点看JDK源码(二)java.util.List liuyuhang原创,未经允许进制转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 List译为表,一览表, ...

  3. 一点一点看JDK源码(三)java.util.ArrayList 前偏

    一点一点看JDK源码(三)java.util.ArrayList liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 ArrayLi ...

  4. 一点一点看JDK源码(四)java.util.ArrayList 中篇

    一点一点看JDK源码(四)java.util.ArrayList 中篇 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 在前篇中 ...

  5. 一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach

    一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 代 ...

  6. 一点一点看JDK源码(五)java.util.ArrayList 后篇之sort与Comparator

    一点一点看JDK源码(五)java.util.ArrayList 后篇之sort与Comparator liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JD ...

  7. 一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList

    一点一点看JDK源码(五)java.util.ArrayList 后篇之SubList liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) S ...

  8. 一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历

    一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看J ...

  9. 一点一点看JDK源码(五)java.util.ArrayList 后篇之removeIf与Predicate

    一点一点看JDK源码(五)java.util.ArrayList 后篇之removeIf与Predicate liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点 ...

随机推荐

  1. linux 共享目录

    1. 文件上传遇到多物理机多实例时,怎么处理呢? ftp, 文件同步, 目录共享 这里用目录共享来一把. 2. 操作流程 物理机两台 192.168.1.88  192.168.1.166 2.1 服 ...

  2. C# Winform窗体和控件自适应大小

    1.在项目中创建类AutoSizeForm AutoSizeForm.cs文件代码: using System; using System.Collections.Generic; using Sys ...

  3. python小练习2

    结果 代码 鞋子价格=0 男孩价格=0 爆米花价格=0 计算完毕=0 for 鞋子动态价格 in range(0,20): if (计算完毕==1): break; #print("鞋子动态 ...

  4. qt 创建资源文件

    我们编写的gui可能需要一些额外的资源(比如贴图用的图片),可用资源文件统一管理.以下以图片为例. 用qt creator 打开工程,为工程新建资源文件: 命名为“项目名.prc”,(此处为“cloc ...

  5. Linux-vi/vim编辑器常用命令与用法

    vi/vim是什么? Linux世界几乎所有的配置文件都是以纯文本形式存在的,而在所有的Linux发行版系统上都有vi编辑器,因此利用简单的文字编辑软件就能够轻松地修改系统的各种配置了,非常方便.vi ...

  6. oracle大量数据删除

    oracle有个数据表现在已经有2500万条数据了,软件用到这个表的数据时就变的特别慢,所以准备把一个月以前的数据全部清除. 我的步骤是(下边操作都是在plsql中运行的) 1.首先 将这个月的数据导 ...

  7. Redis源码学习1-sds.c

    https://github.com/huangz1990/redis-3.0-annotated/blob/unstable/src/sds.c#L120 /* SDSLib, A C dynami ...

  8. 用java读取多种文件格式的文件(pdf,pptx,ppt,doc,docx..)

    本文通过开源pdfbox和poi进行处理多种文件格式的文本读入 1.需要的jar的maven坐标: <dependency> <groupId>org.apache.pdfbo ...

  9. SVNKit学习——wiki+简介(二)

    这篇文章是参考SVNKit官网在wiki的文档,做了个人的理解~ 首先抛出一个疑问,Subversion是做什么的,SVNKit又是用来干什么的? 相信一般工作过的同学都用过或了解过svn,不了解的同 ...

  10. 《C++ Primer Plus》读书笔记之二—复合类型

    二.第四章 复合类型  1.C-风格字符串:C-风格字符串具有一种特殊的性质:以空字符结尾,空字符被写成\0,其ASC||编码为0,用来标记字符串的结尾.例如: char dog[5]={'b','e ...