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的辨析》

发布了47 篇原创文章 · 获赞 108 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/Lagrantaylor/article/details/78941983