咖啡兔🐰源码系列 :01 - 集合容器源码

242 阅读3分钟

前言 :

我们在JAVA开发中经常会使用到容器这一设计结构。JAVA 容器框架中设计了许多不同的容器,例如:开发中经常使用到的ArrayList, LinkedList , HashMap这些。 一般来说,容器在分类上可以分为:

  • Collection
  • Map

我们换个角度去看,其实容器的数据结构可以细分为以下几个部分:

  1. List

  2. set

  3. Queue

  4. Map

这四个不同的数据结构结合容器的设计理念,衍生出来许多不同的容器设计。

日常使用到的集合类都是通过继承这两个类来实现不同场景的设计,那么为什么要设计容器这个概念,容器框架是如何设计实现的?不同的容器之间的共性以及不同之处又是在哪?集合类的设计实现了哪些特殊的机制?

这一系列的问题便是咖啡兔要去探寻的秘密。

Collection 的起源:

Collection 的起源 :Iterable 接口

List ,Set , Queue 这类结构的集合类,都可以实现遍历的方法 ==forEach()== ,而具体实现源头就是 Iterable 接口。

Collection 接口继承了Iterable 接口的方法,然后其他的List ,Set , Queue 等都是继承了Collection接口,这样看来Iterable就相当于这一脉的祖师爷的存在。

那么我们来研究一下这个祖师爷 有哪些独门秘籍:

迭代器 Iterable

public interface Iterable : 是对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。迭代器与枚举有两点不同:

  • 迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。
  • 方法名称得到了改进。

(上述为官方API文档的解释)

所以 Iterable 接口属于是JAVA集合框架中的顶级接口,所有实现的接口都可以通过迭代器来遍历自身的元素。

/**
     * Returns an iterator over elements of type {@code T}.
     * 返回{@code T}类型元素的迭代器。
     * @return an Iterator.
     */
    Iterator<T> iterator();

迭代器的接口定义如下所示:(以下源码是基于JDK 1.8 )

public interface Iterator<E> {
   
    boolean hasNext();

    E next();
  
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

Iterator 和 Enumeration 接口最大的不同点在于:

  1. Iterator 相比于 Enumeration 多出了 remobe() 方法 以及 forEachRemaining() 方法 (forEachRemaining 是1.8 以后加入)
  2. 将原来Enumeration的方法名字改变为了: hasMoreElements改为了hasNext, nextElements改成了next

在JDK 1.1 版本使用的是Enumeration 类来实现 ,但是到了1.2 版本的时候更换为 Iterator 。

在使用迭代器的过程中,是使用 Iterator 遍历集合的时候是不可以直接调用集合的删除或者添加方法来修改集合的结构,这样会抛出ConcurrentModificationException(JDK 1.6)。必须使用remove() 方法进行删减。(在JDK 1.8 中是抛出 UnsupportedOperationException 异常)

**hasNext() : ** 当迭代器有更多的元素的时候就返回 true。 换句话来说就是 当存在下一个元素的时候,就返回true,如果不存在就返回异常。

**E next() : ** 返回下一个元素,如果没有其他元素就抛出异常:NoSuchElementException

**remove() : ** 从基础集合中移除此迭代器返回的最后一个元素(可选操作)。每次对 next() 方法的调用只能调用一次此方法。如果在迭代过程中以任何方式(而不是通过调用此remove方法)修改基础集合,则会抛出 UnsupportedOperationException 不支持的操作异常。

forEachRemaining(Consumer<? super E> action) : 对剩余的每个元素执行给定的操作,直到所有元素都已处理或操作引发异常。如果指定了迭代顺序,则按迭代顺序执行操作。操作引发的异常被中继到调用方。如果没有元素进行迭代则抛出空指针异常 NullPointerException 。

![image-20200915172640719](/Users/jinmo/Library/Application Support/typora-user-images/image-20200915172640719.png)