java源码之Spliterator
前言
Spliterator是一个可分割迭代器(splitable iterator),可以和iterator顺序遍历迭代器一起看。jdk1.8发布后,对于并行处理的能力大大增强,Spliterator就是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator,后面我们也会结合ArrayList中的spliterator()一起解析。
方法
tryAdvance
- jdk源码
boolean tryAdvance(Consumer<? super T> action)
单个对元素执行给定的动作,如果有剩下元素未处理返回true,否则返回false
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("1");
Spliterator<String> spliterator = strings.spliterator();
boolean flag1 = spliterator.tryAdvance(System.out::println);
boolean flag2 = spliterator.tryAdvance(System.out::println);
System.out.println(flag1);
System.out.println(flag2);
}
代码在执行 boolean flag1 = spliterator.tryAdvance(System.out::println);在控制台打印了1 ,在执行System.out.println(flag1)打印了true;这表明tryAdvance获取spliterator中的元素并执行相应的操作。
代码在执行 boolean flag2 = spliterator.tryAdvance(System.out::println)控制台无打印信息,在执行System.out.println(flag2)打印了false,说明在执行tryAdvance时,会将index+1在执行元素(参照java.util.ArrayList.ArrayListSpliterator得出的结论)
spliterator.tryAdvance与iterator.hasnext和iterator.next连用有异曲同工之妙,获取元素并执行制定操作。
forEachRemaining
- jdk源码
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
对每个剩余元素执行给定的动作,依次处理,直到所有元素已被处理或被异常终止。默认方法调用tryAdvance方法
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("111");
strings.add("112");
Spliterator<String> spliterator = strings.spliterator();
spliterator.forEachRemaining(System.out::println);
}
在执行spliterator.forEachRemaining(System.out::println)时,循环输出strings下的所有元素。
从源代码可以看出,forEachRemaining其实就是对于tryAdvance的重组调用
- 注意
如果你先调动tryAdvance在调用forEachRemaining,那forEachRemaining不回调用tryAdvance已经调用的元素。
trySplit
- jdk源码
Spliterator<T> trySplit();
对原有的Spliterator分割,返回一个新的Spliterator迭代器
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("111");
strings.add("112");
Spliterator<String> spliterator = strings.spliterator();
Spliterator<String> spliterator2 = spliterator.trySplit();
spliterator.forEachRemaining(System.out::println);
spliterator2.forEachRemaining(System.out::println);
}
代码在执行 spliterator.forEachRemaining(System.out::println)时输出112,在执行 spliterator2.forEachRemaining(System.out::println)时输出111。trySplit会将原有的Spliterator中的数据均分。原有的数据被tryAdvance或者forEachRemaining使用过的数据不会算在均分的元素中。
estimateSize
- jdk源码
long estimateSize();
用于估算还剩下多少个元素需要遍历
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("1");
Spliterator<String> spliterator = strings.spliterator();
System.out.println(spliterator.estimateSize());
}
代码 System.out.println(spliterator.estimateSize())控制台打印1;
原有的数据被tryAdvance或者forEachRemaining使用过的数据不会算在计数的元素中。
getExactSizeIfKnown
- jdk源码
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
当迭代器拥有SIZED特征时,返回剩余元素个数;否则返回-1
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("1");
strings.add("2");
strings.add("3");
strings.add("4");
Spliterator<String> spliterator = strings.spliterator();
spliterator.tryAdvance(System.out::println);
System.out.println(spliterator.getExactSizeIfKnown());
}
代码System.out.println(spliterator.getExactSizeIfKnown())返回3;
characteristics
- jdk源码
int characteristics();
返回当前对象有哪些特征值
各种特征值:
特征 | 十六进制 | 十进制 | 含义 |
---|---|---|---|
ORDERED | 0x00000010 | 16 | 元素之间是有顺序的 |
DISTINCT | 0x00000001 | 1 | 元素之间不会重复 |
SORTED | 0x00000004 | 4 | 元素遵循定义的排序顺序 |
SIZED | 0x00000040 | 64 | 表示长度为有限个 |
NONNULL | 0x00000100 | 256 | 表示元素不能为空 |
IMMUTABLE | 0x00000400 | 1024 | 元素源不能修改(不能添加,替换或删除元素) |
CONCURRENT | 0x00001000 | 4096 | 多个线程安全同时修改元素源而无需外部同步 |
SUBSIZED | 0x00004000 | 16384 | 迭代器所分割得到的子迭代器也是有序的 |
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("1");
strings.add("2");
strings.add("3");
strings.add("4");
Spliterator<String> spliterator = strings.spliterator();
System.out.println(spliterator.characteristics());
}
代码控制台打印结果为16464;16464=16384+64+16所以该数组有的特征值为SUBSIZED,SIZED,ORDERED。
hasCharacteristics
- jdk源码
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
是否具有当前特征值
- demo
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("1");
strings.add("2");
strings.add("3");
strings.add("4");
Spliterator<String> spliterator = strings.spliterator();
System.out.println(spliterator.hasCharacteristics(Spliterator.ORDERED));
System.out.println(spliterator.hasCharacteristics(Spliterator.SIZED));
System.out.println(spliterator.hasCharacteristics(Spliterator.SUBSIZED));
System.out.println(spliterator.hasCharacteristics(Spliterator.CONCURRENT));
}
代码执行System.out.println(spliterator.hasCharacteristics(Spliterator.ORDERED)),System.out.println(spliterator.hasCharacteristics(Spliterator.SIZED)),ystem.out.println(spliterator.hasCharacteristics(Spliterator.SUBSIZED))均返回true;在执行System.out.println(spliterator.hasCharacteristics(Spliterator.CONCURRENT))打印false。
getComparator
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
如果Spliterator的list是通过Comparator排序的,则返回Comparator;如果Spliterator的list是自然排序的 ,则返回null;其他情况下抛错。