1、Iterable 接口
Iterable,即迭代器的意思。其作用是为集合类提供for-each循环遍历的支持,只要让一个类实现这个接口,该类的对象就可以成为for-each循环遍历的目标。换句话说,想让一个Java对象支持for-each遍历,只要让它的类实现Iterable接口即可。
public interface Iterable<T> {
// 在类型的元素上返回迭代器
Iterator<T> iterator();
// 对Iterable的每个元素执行给定的操作,直到处理完所有元素或操作引发异常。
// 除非实现类另有指定,否则按迭代顺序(如果指定了迭代顺序)执行操作
// 操作引发的异常将中继到调用方
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);
}
}
2、Iterator 接口
Iterator即迭代器,是一个由集合框架提供、用于遍历一个集合的接口,并且访问集合的元素时是有序访问的。我们可以这样理解,集合的迭代器包含集合的所有元素,它们在遍历时按照一定的迭代次序进行。在迭代器中有一个光标指向最先迭代的元素,当执行next()方法时,将该元素从迭代器中删掉,然后光标往前移动指向剩下的元素中最早迭代的元素。
Iterator与枚举有些类似,不过它们有两点不同:
1)迭代器允许调用者在迭代期间从迭代器所指向的集合中删除元素
2)迭代器中的方法名称与枚举相比得到了改进(迭代器可以说是用来代替Enumeration的)
public interface Iterator<E> {
// 判断Iterator是否有更多的元素
boolean hasNext();
// 返回iteration中的下一个元素
E next();
// 从基础集合中删除此迭代器返回的最后一个元素
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 对每个剩余的元素执行给定的操作,直到所有元素都被处理或操作引发异常。
// 如果指定了迭代顺序,则按迭代顺序执行操作。操作引发的异常将中继到调用方。
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
3、Spliterator 接口
JDK8 引入
Spliterator是一个可分割迭代器(splitable iterator),可以和iterator顺序遍历迭代器一起看。jdk1.8发布后,对于并行处理的能力大大增强,Spliterator就是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator
Iterator 和 Spliterator 相比,但一个是顺序遍历,一个是并行遍历
3.1、成员变量
public interface Spliterator<T> {
// 表示迭代器需要按照其原始顺序迭代其中元素的
public static final int ORDERED = 0x00000010;
// 迭代器中的元素是没有重复的
public static final int DISTINCT = 0x00000001;
// 迭代器是按照某种方式排序的顺序迭代其中元素的
public static final int SORTED = 0x00000004;
// 表示迭代器将要迭代的元素的个数是可计数的,有界的
public static final int SIZED = 0x00000040;
// 迭代器迭代的元素是没有值为`null`的
public static final int NONNULL = 0x00000100;
// 迭代器迭代的元素是不可改变的,也不可以增加、替换和删除
public static final int IMMUTABLE = 0x00000400;
// 表示迭代器的数据源是线程安全的
public static final int CONCURRENT = 0x00001000;
// 表示当前迭代器所有的子迭代器(直接的或者间接的),都是`SIZED`和`SUBSIZED`的
public static final int SUBSIZED = 0x00004000;
}
例如一个Collection实例的spliterator会报告一个SIZED的特征,一个Set实例会报告一个DISTINCT特征,等。
如果一个迭代器没有报告IMMUTABLE或者CONCURRENT特征时,其绑定数据源后会检查数据源的结构化改动。后绑定的迭代器是绑定数据源发生在其第一次遍历、第一次拆分、第一次查询大小时,而不是在迭代器创建后立刻绑定数据源。和其它迭代器一样,绑定前对源的修改可以反应在迭代器遍历过程中,而绑定后的对源的修改会导致ConcurrentModificationException异常。
Spliterator的批量遍历方法(forEachRemaining())可以遍历所有元素之后优化遍历并检对源的结构化修改,而不是逐个检查元素并立即抛出失败。
Spliterator提供了estimateSize()方法用来估算迭代器中剩余元素的数量,理想情况下,它能够准确的计算迭代器中能够成功迭代的元素的数量,即使是在不准切的时候,其结果依然能够为对迭代器的下一步操作,如是直接迭代剩余元素还是继续分割迭代器提供依据。
尽管Spliterator为并发迭代提供了入口,但它依旧是线程不安全的。相反,spliterator的并发实现必须保证其在同一个时刻只有一个线程访问。调用trySplit()的线程可能会后续将迭代器交给其他线程进行迭代或者继续分割,并发的分割或者迭代同一个迭代器会导致不确定的结果。如果需要将迭代器由一个线程递交给另一个线程,需要保证递交前没有使用tryAdvance()消费任何元素。
Spliterator为原始类型中的int、long、double提供了专门的子类并默认实现了tryAdvance(java.util.function.Consumer) 和forEachRemaining(java.util.function.Consumer)。就是后面讲到的4个内部接口。
3.2、方法
// 单个对元素执行给定的动作,如果有剩下元素未处理返回true,否则返回false
boolean tryAdvance(Consumer<? super T> action);
// 对每个剩余元素执行给定的动作,依次处理,直到所有元素已被处理或被异常终止。默认方法调用tryAdvance方法
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
// 对任务分割,返回一个新的Spliterator迭代器
Spliterator<T> trySplit();
// 用于估算还剩下多少个元素需要遍历
long estimateSize();
// 当迭代器拥有SIZED特征时,返回剩余元素个数;否则返回-1
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
// 返回当前对象有哪些特征值
int characteristics();
// 是否具有当前特征值
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
// 如果Spliterator的list是通过Comparator排序的,则返回Comparator
// 如果Spliterator的list是自然排序的 ,则返回null
// 其他情况下抛错
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
3.3、内部接口
(1)OfPrimitive
public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
extends Spliterator<T> {
@Override
T_SPLITR trySplit();
@SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action);
@SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
}
(2)OfInt
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
@Override
OfInt trySplit();
@Override
boolean tryAdvance(IntConsumer action);
@Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
@Override
default boolean tryAdvance(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
return tryAdvance((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
return tryAdvance((IntConsumer) action::accept);
}
}
@Override
default void forEachRemaining(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
forEachRemaining((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)");
forEachRemaining((IntConsumer) action::accept);
}
}
}
(3)OfLong
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
OfLong trySplit();
@Override
boolean tryAdvance(LongConsumer action);
@Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
@Override
default boolean tryAdvance(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
return tryAdvance((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)");
return tryAdvance((LongConsumer) action::accept);
}
}
@Override
default void forEachRemaining(Consumer<? super Long> action) {
if (action instanceof LongConsumer) {
forEachRemaining((LongConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)");
forEachRemaining((LongConsumer) action::accept);
}
}
}
(4)OfDouble
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
OfDouble trySplit();
@Override
boolean tryAdvance(DoubleConsumer action);
@Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
@Override
default boolean tryAdvance(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
return tryAdvance((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)");
return tryAdvance((DoubleConsumer) action::accept);
}
}
@Override
default void forEachRemaining(Consumer<? super Double> action) {
if (action instanceof DoubleConsumer) {
forEachRemaining((DoubleConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)");
forEachRemaining((DoubleConsumer) action::accept);
}
}
}
3.4、实现样例
以ArrayListSpliterator为例说明Spliterator的实现:
static final class ArrayListSpliterator<E> implements Spliterator<E> {
//ArrayList数据源的对象引用
private final ArrayList<E> list;
private int index; // 起始位置所有,会被advance()和split()函数修改。
private int fence; // 结束位置,-1表示到最后一个元素
private int expectedModCount; // initialized when fence set
ArrayListSpliterator(ArrayList<E> list, int origin, int fence, int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
if ((hi = fence) < 0) {
if ((lst = list) == null)
hi = fence = 0;
else {
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
// 每次分割,都将原来的迭代器等分为两个,并返回索引靠前的那个
public ArrayListSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : new ArrayListSpliterator<E>(list, lo, index = mid, expectedModCount);
}
// 使用action消费下一个元素
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked")
E e = (E)list.elementData[i];
action.accept(e);
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
// 批量消费所有未迭代的元素
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
} else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
//估算将要迭代的元素的数量
public long estimateSize() {
return (long) (getFence() - index);
}
//特征值,对于ArrayListSpliterator,其迭代顺序是按照原始顺序迭代的,而且可以预估数量。
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
3.5、使用样例
import java.util.ArrayList;
import java.util.Spliterator;
import java.util.function.Consumer;
public class IteratorTest {
public static void main(String[] args) {
ArrayList<String> arrays = new ArrayList<String>();
arrays.add("a");
arrays.add("b");
arrays.add("c");
arrays.add("d");
arrays.add("e");
arrays.add("f");
arrays.add("g");
arrays.add("h");
arrays.add("i");
arrays.add("j");
arrays.remove("j");
Spliterator<String> p = arrays.spliterator();
Spliterator<String> s1 = p.trySplit();
Spliterator<String> s2 = p.trySplit();
System.out.println("p.consume :");
p.forEachRemaining(new Consumer<String>() {
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("s1.consume");
s1.forEachRemaining(new Consumer<String>() {
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("s2.consume");
s2.forEachRemaining(new Consumer<String>() {
public void accept(String s) {
System.out.println(s);
}
});
}
}
结果: