紧接上文《JAVA8 Spliterator 并行迭代器用法以及 自定义Spliterator (一)》
上文实现了demo 说明迭代器一般的切割规律,本文主要介绍如何实现自定义spliterator 以及根据自定义迭代器说明各个方法的作用,本文主要实现了一个简化自定义迭代器MySpliterator 功能简单,主要是为了说明,大家个根据自己业务需求开发
MySpliterator 功能:
1.仅可且只能进行两次分割,超过两次就不允许分割(实际情况肯定不肯是这样,需要根据总数进行切割次数计算,但建议先计算出线程数然后再计算切割次数)
2.输出遍历数据以便查看情况
闲话不多说,上代码
class MySpliterator implements Spliterator {
private int[] array;
private int origin;
private int fence;
private boolean canSplit = true;
private String threadName;
private MySpliterator(int[] array, String threadName) {
this.origin = 0;
this.array = array;
this.fence = array.length;
this.threadName = threadName;
}
private MySpliterator(int[] array, boolean canSplit, String threadName) {
this.origin = 0;
this.array = array;
this.fence = array.length - 1;
this.canSplit = canSplit;
this.threadName = threadName;
}
@Override
public boolean tryAdvance(Consumer action) {
if (origin <= fence) {
int x = array[origin++];
action.accept(x);
System.out.println(threadName + ":" + x);
return true;
} else
return false;
}
@Override
public Spliterator trySplit() {
//计算中间值
int mid = ((origin + fence) >>> 1) & ~1;
fence = mid;
System.out.println("进行一次切割");
return new MySpliterator(Arrays.copyOfRange(array, mid + 1, array.length), false, "线程2");
}
@Override
public long estimateSize() {
if (canSplit) {
canSplit = false;
return (fence - origin) / 2;
} else {
return 0;
}
}
@Override
public int characteristics() {
return ORDERED | SIZED | IMMUTABLE | SUBSIZED;
}
}
@Test
public void streamMySpliteratorTest() {
int[] array = IntStream.range(0, 100).toArray();
MySpliterator mySpliterator = new MySpliterator(array, "线程1");
Stream stream = StreamSupport.stream(mySpliterator, true);
List integers = stream.map(x -> x+1).collect(Collectors.toList());
Assert.assertEquals(integers.size(),100);
}
输出
进行一次切割 线程1:0 线程1:1 线程1:2 线程1:3 线程1:4 线程1:5 线程1:6 线程1:7 线程1:8 线程1:9 线程1:10 线程1:11 线程1:12 线程1:13 线程1:14 线程1:15 线程1:16 线程1:17 线程1:18 线程1:19 线程2:51 线程1:20 线程1:21 线程1:22 线程1:23 线程1:24 线程1:25 线程1:26 线程1:27 线程1:28 线程1:29 线程1:30 线程1:31 线程1:32 线程1:33 线程1:34 线程2:52 线程1:35 线程1:36 线程2:53 线程2:54 线程2:55 线程2:56 线程2:57 线程2:58 线程2:59 线程2:60 线程2:61 线程2:62 线程2:63 线程2:64 线程1:37 线程2:65 线程2:66 线程2:67 线程2:68 线程2:69 线程2:70 线程2:71 线程2:72 线程2:73 线程2:74 线程2:75 线程2:76 线程2:77 线程2:78 线程2:79 线程2:80 线程2:81 线程2:82 线程2:83 线程2:84 线程2:85 线程2:86 线程2:87 线程2:88 线程2:89 线程2:90 线程2:91 线程2:92 线程2:93 线程2:94 线程2:95 线程1:38 线程1:39 线程1:40 线程1:41 线程1:42 线程1:43 线程1:44 线程1:45 线程1:46 线程1:47 线程1:48 线程1:49 线程1:50 线程2:96 线程2:97 线程2:98 线程2:99
看到结果确实是只切割了一次,并且是平均切割,何时启动触发的
tryAdvance 呢,是在启动遍历的时候或者统计的时候比如
在调用这个时候就会开始启动遍历,然后map的consumer 会映射到到spliterator的tryadance
如下



