JDK1.8集合框架源码阅读(二)——Iterable接口

功能简介

Iterable接口作为Collection的根接口,负责实现所有集合类的for-each语句功能。

Iterable类定义如下:

/**
 * 实现此接口允许对象成为“for-each loop”语句的目标。
 */
public interface Iterable<T> {
    Iterator<T> iterator();
    
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

tips:default是JDK 1.8 新加的关键字,Java允许该关键字注明的方法在接口中有默认实现。

下面针对每个方法进行详细的介绍。

方法介绍

  1. iterator
Iterator<T> iterator();

该方法用来返回一个迭代器对象,是Iterable的主要方法。
回想我们使用迭代器的场景,是不是开头会有这样一段语句(假如迭代ArrayList):

Iterator<ArrayList> iterator = arrayList.iterator();

其实,在每个集合类的内部都对iterator()方法进行了覆写以实现自身的迭代操作。
所以当调用集合的iterator(),会返回该集合所实现的特定迭代器对象

而作为根类型的Iterable接口提供的这个方法,恰恰就是方便各个集合对其重写实现各自的迭代器。
这也是一种设计模式的思想——迭代器模式,对该设计模式的详细介绍可以参考另一篇文章:
Java 设计模式通关之路——迭代器模式


  1. forEach
default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

该方法用来对每个集合的元素进行遍历,可以看到其底层实现也是用的for-each语句,那么这两者有什么区别呢?
作为Java8新加的方法,该方法支持对集合中的元素做一些自定义的操作。

可以看到,传入的类型是Consumer类型,而Consumer类型是Java8新增的一个消费型函数式接口,其目的是为了支持Java8新增的Lombda表达式,通过方法的实现来执行具体操作。

这里简单说一下Consumer的用法便于理解,你可以这样去使用Consumer

Consumer<Integer> sop = x -> System.out.println("This number is " + x);
sop.accept(1);
/* Output
This number is 1
*/

也就是说,一个Consumer对象实例可以代表一个Lombda表达式所进行的操作。
accept()方法就是对传入的指定类型执行所定义的操作。

回到forEach()方法中来,该方法的入参需要表明你要对该集合中的元素所要执行的自定义操作
而在for循环中对集合的每个元素执行给定的操作,直到遍历完毕或者引发异常。

  1. spliterator
default Spliterator<T> spliterator() {
    return Spliterators.spliteratorUnknownSize(iterator(), 0);
}

该方法主要用于对集合元素进行分割遍历,通常每个集合中对其进行了自身的默认实现。
Spliterator是一个可分割迭代器,目的是为了并行遍历元素。
可以看一下对ArrayList集合进行分割迭代的结果:

List<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
arrayList.add(6);
arrayList.add(7);
arrayList.add(8);
arrayList.add(9);

Spliterator<Integer> spl = arrayList.spliterator();
spl.forEachRemaining(value -> System.out.println("Init : " + value));

/* Output
Init : 1
Init : 2
Init : 3
Init : 4
Init : 5
Init : 6
Init : 7
Init : 8
Init : 9
*/

未分割时,分割迭代器将集合元素全部迭代出来。

而进行一次分割之后的结果呢:

··· // 省略赋值操作

Spliterator<Integer> spl = arrayList.spliterator();
Spliterator<Integer> spl1 = spl.trySplit();
spl1.forEachRemaining(value -> System.out.println("First : " + value));

/* Output
First : 1
First : 2
First : 3
First : 4
*/

可以看到,只迭代了一半的元素,而分割两次的结果呢:

··· // 省略赋值操作

Spliterator<Integer> spl = arrayList.spliterator();
Spliterator<Integer> spl1 = spl.trySplit();
Spliterator<Integer> spl2 = spl1.trySplit();
spl2.forEachRemaining(value -> System.out.println("Second : " + value));

/* Output
Second : 1
Second : 2
*/

只迭代了一半的一半。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值