对java8 StreamAPI的扩展

java8的流(Stream API)已经提供了很强大的api接口了,满足日常开发的绝大部分需要,但是还是有些欠缺比如 java9才增加的两个api takeWhile dropWhile

takeWhile() 方法使用一个断言作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false。

**dropWhile()**与takeWhile相反,使用一个断言作为参数,直到断言语句第一次返回 true 才返回给定 Stream 的子集。

还有不爽的地方是同一个流只能执行一次流水线操作,完成后这个流就废了。要执行第二个次流水线操作就必须重新创建流。原因可以看这个java8 Stream流水线实现分析

通过Spliterator的延迟绑定能力实现对java8 流的扩展

takeWhile

public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
    Spliterator<T> spliterator = stream.spliterator();
    return StreamSupport.stream(new Spliterator<T>() {
        boolean stillGoing = false;

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            boolean hasNext = spliterator.tryAdvance(item -> {
                if (!predicate.test(item)) {
                    action.accept(item);
                    stillGoing = true;
                } else {
                    stillGoing = false;
                }
            });
            return hasNext && stillGoing;
        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }

        @Override
        public long estimateSize() {
            return 0;
        }

        @Override
        public int characteristics() {
            return 0;
        }
    }, false);
}
public static void main(String[] args) {
    takeWhile(Stream.of("a", "b", "", "c", "d"), String::isEmpty).forEach(System.out::print);//ab
}

dropWhile

public static <T> Stream<T> dropWhile(Stream<T> stream, Predicate<? super T> predicate) {
    Spliterator<T> spliterator = stream.spliterator();
    return StreamSupport.stream(new Spliterator<T>() {
        boolean canGo = false;

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            return spliterator.tryAdvance(item -> {
                if (canGo) {
                    action.accept(item);
                } else {
                    canGo = predicate.test(item);
                }
            });

        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }

        @Override
        public long estimateSize() {
            return 0;
        }

        @Override
        public int characteristics() {
            return 0;
        }
    }, false);
}
public static void main(String[] args) {
    dropWhile(Stream.of("a", "b", "", "c", "d"), String::isEmpty).forEach(System.out::print);//cd
}

在同一个流中执行多个操作

思路大概是这样的

StreamForker 记录对流的操作,通过ForkerConsumer将原来流中的元素分发生成多个子流(有几个操作,就有几个子流),在子流中调用用户的操作function

具体实现如下

public class StreamForker<T> {
    private final Stream<T> stream;
    //记录对流的操作列表
    private final Map<Object, Function<Stream<T>, ?>> actionMap = new HashMap<>();

    public StreamForker(Stream<T> stream) {
        this.stream = stream;
    }

    public StreamForker<T> fork(Object key, Function<Stream<T>, ?> function) {
        actionMap.put(key, function);
        return this;
    }

    public Results getResults() {
        ForkerConsumer<T> consumer = build();
        try {
            //将元素放入ForkerConsumer分发到子流中
            stream.sequential().forEach(consumer);
        } finally {
            //向子流发送结束标识
            consumer.finish();
        }
        return consumer;
    }

    public ForkerConsumer<T> build() {
        List<BlockingQueue<T>> queues = new ArrayList<>();
        //获取结果map
        Map<Object, Future<?>> futureMap = actionMap.entrySet().stream()
                .reduce(new HashMap<>(), (map, entry) -> {
                    map.put(entry.getKey(), getResult0(queues, entry.getValue()));
                    return map;
                }, (map1, map2) -> {
                    map1.putAll(map2);
                    return map1;
                });
        return new ForkerConsumer<>(queues, futureMap);
    }
	//异步获取子流的结果
    private Future<?> getResult0(List<BlockingQueue<T>> queues, Function<Stream<T>, ?> function) {
        BlockingQueue<T> queue = new LinkedBlockingQueue<>();
        queues.add(queue);
        Spliterator<T> spliterator = new SubSpliterator<>(queue);
        Stream<T> souce = StreamSupport.stream(spliterator, false);
        return CompletableFuture.supplyAsync(() -> function.apply(souce));
    }

    public interface Results {
        <R> R get(Object key);
    }

    static class SubSpliterator<T> implements Spliterator<T> {
        private final BlockingQueue<T> queue;

        public SubSpliterator(BlockingQueue<T> queue) {
            this.queue = queue;
        }

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            T t;
            while (true) {
                try {
                    t = queue.take();
                    break;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (t != ForkerConsumer.END_OF_STREAM) {
                action.accept(t);
                return true;
            }
            return false;
        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }

        @Override
        public long estimateSize() {
            return 0;
        }

        @Override
        public int characteristics() {
            return 0;
        }
    }

    static class ForkerConsumer<T> implements Consumer<T>, Results {
        static final Object END_OF_STREAM = new Object();
        private final List<BlockingQueue<T>> queues;
        //存放子流结果
        private final Map<Object, Future<?>> results;

        public ForkerConsumer(List<BlockingQueue<T>> queues, Map<Object, Future<?>> results) {
            this.queues = queues;
            this.results = results;
        }

        void finish() {
            //放入结束标识
            accept((T) END_OF_STREAM);
        }

        @Override
        public <R> R get(Object key) {
            try {
                return ((Future<R>) results.get(key)).get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void accept(T t) {
            //接受到元素放入各个子流的队列中
            queues.forEach(q -> q.offer(t));
        }
    }

    public static void main(String[] args) {
        List<String> list = Arrays.asList("test", "jiang", "an", "wei");
        StreamForker.Results results = new StreamForker<>(list.stream())
                .fork("test1", stringStream -> stringStream.sorted().filter(x -> x.equals("test")).findAny())
                .fork("count", Stream::count)
                .fork("join", stringStream -> stringStream.collect(Collectors.joining(",")))
                .getResults();
        Optional<String> test1 = results.get("test1");
        System.out.println(test1.get());
        System.out.println("" + results.get("count"));
        System.out.println("" + results.get("join"));
    }
}
              .getResults();
        Optional<String> test1 = results.get("test1");
        System.out.println(test1.get());
        System.out.println("" + results.get("count"));
        System.out.println("" + results.get("join"));
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值