JAVA8 Spliterator 并行迭代器用法以及 自定义Spliterator (二)

紧接上文《JAVA8 Spliterator 并行迭代器用法以及 自定义Spliterator (一)》

上文实现了demo 说明迭代器一般的切割规律,本文主要介绍如何实现自定义spliterator 以及根据自定义迭代器说明各个方法的作用,本文主要实现了一个简化自定义迭代器MySpliterator 功能简单,主要是为了说明,大家个根据自己业务需求开发

MySpliterator 功能:

1.仅可且只能进行两次分割,超过两次就不允许分割(实际情况肯定不肯是这样,需要根据总数进行切割次数计算,但建议先计算出线程数然后再计算切割次数)

2.输出遍历数据以便查看情况

闲话不多说,上代码

/**
     * @desc: 自定义Spliterator ,只能进行一次切割,然后输出遍历元素
     */
    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;
        }


        /**
         * @desc: 处理具体某元素,如果成功则数据角标+1并返回true,失败则返回false,相当于iterator hasNext和next一体了
         */
        @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;
        }

        /**
         * @desc: 切割数据为一半一半,如果切割过一次则canSplit变为false,下次再切割则返回null
         */
        @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");

        }

        /**
         * @desc: 剩余数量,用于评估是否调用切割功能,如果返回<=0则无法切割,将不会调用trySplit
         */
        @Override
        public long estimateSize() {

            if (canSplit) {
                canSplit = false;
                return (fence - origin) / 2;
            } else {
                return 0;
            }
        }

         /**
         * CONCURRENT 特征值表示可以通过多个线程安全同时修改元素源(允许添加,替换和/或删除),而无需外部同步。
         * DISTINCT 特性值这标志着,对于每对遇到的元件 x, y , !x.equals(y) 。
         * IMMUTABLE 特征值表示元素源不能在结构上进行修改; 也就是说,不能添加,替换或删除元素,因此在遍历过程中不会发生这种更改。
         * NONNULL 特征值表示源保证遇到的元素不会为 null
         * ORDERED 特征值表示为元素定义遇到顺序
         * SIZED 表示在遍历或 estimateSize()之前从 estimateSize()返回的值的特征值表示在没有结构源修改的情况下表示完全遍历将遇到的元素数量的精确计数的有限大小。
         * SORTED 特征值表示遇到的顺序遵循定义的排序顺序。
         * SUBSIZED 特征值这标志着从产生的所有Spliterators trySplit()将是既 SIZED和 SUBSIZED
         */

        @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<Integer> stream = StreamSupport.stream(mySpliterator, true);
        List<Integer> 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

如下

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峡谷电光马仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值