Java集合源码分析(三)-Iterable

159 阅读2分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

Iterable 是 Collection 实现的接口,Collection 是 AbstractCollection 实现的接口,AbstractCollection 是 List、Set 的父类

graph LR
A[Iterable] --> B(Collection) --> C(AbstractCollection)
C --> D(List)
C --> E(Set)

源码

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 loop” 语句的目标
 * 查看 For-each Loop
 *
 * @param <T> 迭代器返回的元素类型
 *
 * @since 1.5
 * @jls 14.14.2 增强 for 声明
 */
public interface Iterable<T> {
    
    /**
     * 返回 T 类型的迭代器
     * @return 迭代器
     */
    Iterator<T> iterator();

    /**
     * 对迭代器的每个元素进行给定操作,直到所有元素已经被处理或者操作抛出异常
     * 除非实现类有其他的明确规定,否则按迭代顺序执行操作(如果明确了迭代顺序)
     * 操作导致的异常转发给调用方
     *
     * @implSpec
     * 默认实现的行为就像:
     * <pre>{@code
     *     for (T t : this)
     *         action.accept(t);
     * }</pre>
     *
     * @param action 为每个元素执行的操作
     * @throws NullPointerException 如果指定的操作为空
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * 根据这个迭代器描述的元素创建一个分离器
     * 
     * 默认实现会从可迭代的迭代器中创建一个 early-binding 分离器
     * 这个分离器继承可迭代的迭代器的 fail-fast 属性
     *
     * 默认实现通常应该被重写
     * 根据默认实现返回的分离器分离性能很差,长度不固定,并且不能汇报任何分离器的特征
     * 实现类几乎总可以提供更好的实现
     *
     * @return a {@code Spliterator} over the elements described by this
     * {@code Iterable}.
     * @since 1.8
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

总结

  • Iterable 从 JDK1.5 开始已经有了
  • iterator() 返回泛型的迭代器
  • forEach()spliterator() 是 Java8 才加入的方法
  • forEach() 是遍历迭代器的方法,具体使用代码
    for (T t : this)
        action.accept(t);
    
  • spliterator() 返回默认实现的分离器,性能并不好,如果需要使用,应该重写这个方法