Java中集合类源码分析(1)-----Iterable和Iterator源码分析

怀着庄严而圣神的心情,今天打开了Java8的源码.以前用了不少集合内的东西,但也只是会用(当然还有许多不知道的),对于一些集合的选择,原理实现是不求甚解的,也看了不少介绍其结构层次,所以今天决定自己来研读研读.新手轻喷…没人看我就留着以后自己慢慢看了(笑)
Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)
本文从最熟悉的Collection开始,先找其父类(接口),然后向下,挨个问候哈哈哈~
本篇文章是该系列文的第一篇.
工具:eclipse和Java8英文API手册,有道词典

1.Collection接口的父接口—–Iterable接口

打开Collection.class发现其作为一个接口,继承自Iterable接口

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

/** * 实现了这个接口,就可以使这个对象成为 "for-each"循环语句的目标 * 也就是说实现了这个接口,就可用 "for-each"语句,这也是Iterable实现的特征 */
public interface Iterable<T> {

     //返回一个在这个类型<T>里的元素的迭代器
    Iterator<T> iterator();

    /** *对Iterable的类中的每一个元素执行给定的操作,直到所有的元素都处理过了或者动作抛出了异常 *除非是被实现类特别指定,否则动作将以迭代的顺序进行(如果迭代顺序被指定了的话) */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);//验证action是否为null,是的话则抛出NullPointerException 
        for (T t : this) {
            action.accept(t);
        }
    }

    /** *(下面这个Spliterator是Java8才有的,这个名字代表"可分迭代器"(splitable iterator)。 *和Iterator一样, Spliterator也用于遍历数据源中的元素,但它是为了并行执行而设计的。能力有限,以后再说吧) * *创建一个被这个Iterable接口描述的元素上Spliterator。 * * 默认实现从iterable的Iterator中创建一个早期绑定的spliterator。这个spliterator * 继承iterable的iterator的fail-fast性质。 * * 默认实现应该总是被重写。被默认实现返回的spliterator拥有不好分解能力,是不依据指定 * 大小定制的,而且不报告任何spliterator的性质。实现类差不多总是能提供更好的实现。 * */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

2.Iterable中一个重要”组成部分”——Iterator接口

发现Iterable接口中有一个返回Iterator的方法,当然要看一看啦~

package java.util;

import java.util.function.Consumer;

/** * An iterator over a collection. {@code Iterator} takes the place of * {@link Enumeration} in the Java Collections Framework. Iterators * differ from enumerations in two ways: *是一个在集合上的迭代器.迭代器在Java集合框架中替代了Enumeration的位置. *Iterators与enumeration的不同主要有两点: * (1)迭代器允许在迭代过程中从这个集合中移除元素 * (2)方法名称有所改进 * *参数: 被迭代的元素的类型 */
public interface Iterator<E> {
    /** *返回boolean,判断迭代器中是否还有元素()换句话说,如果返回true,则next()将返回一个元素而不是抛出一个异常 * * 返回true,如果还有元素 */
    boolean hasNext();

    /** * Returns the next element in the iteration. *返回迭代器中的下一个元素 * @return 迭代器中的下一个元素 E类型 * @throws NoSuchElementException,当迭代器中没有元素时抛出 */
    E next();

    /** * 从这个collection中移除被迭代器迭代的最后一个元素. * 这个方法可以在每次调用next()后调用一次. * 当迭代器运行时,这个collection被除这个方法的其他方式修改的话,迭代器的行为是不被指定的. * * 默认实现抛出UnsupportedOperationException的一个实例,不执行任何动作。 * *当next()未被调用时,或者remove()方法 已经被最后一个next()用掉后,抛出IllegalStateException *(这意味着:remove()可以删除最后一次看到的元素,不能一次调用两次remove()) */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /** * 验证action是否为空,是的话抛出NonPointerException */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

关于Iterable和Iterator的联系与区别

1.通过源码我们发现Iterable接口里面有一个返回Iteartor的方法,其返回一个Iterator类型的对象(或者说实现了Iterator接口的对象)。那么也就是说,实现了Iterable接口的类可以通过iterator()方法得到一个迭代器,然后后可以调用Iterator类型的方法(上文提到的next(),remove等)
2.还发现实现了Iterable接口的类可以拥有增强的for.这一点只是实现了Iterator的类还不行.
那么可以想象,如果这些集合直接实现Iterator接口,则会导致集合对象中包含当前迭代位置的数据(指针)。当集合在不同方法间进行传递的时候,由于当前迭代位置不可知,所以next()的结果也不可知。除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 而当实现Iterable则不然,每次调用都返回一个从头开始的迭代器,各个迭代器之间互不影响。—–TangowL《Java中Iterable和Iterator的辨析》

    原文作者:java集合源码分析
    原文地址: https://blog.csdn.net/Lagrantaylor/article/details/78941983
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞