java流式编程(十七)dropWhile

目录


前言

在jdk9中,Stream中提供了dropWhile的功能。


一、示例

	@Test
    public void testDropWhile(){
        List<Integer> list = List.of(1, 2, 3, 4, 5, 4, 3, 2, 1);
        Stream<Integer> dropWhile = list.stream().dropWhile(i -> i < 4);
        dropWhile.forEach(System.out::println);
    }

结果

4
5
4
3
2
1

可以看出,开始时小于4的数被drop掉了,后续的数不在drop。

二、原理

在Stream接口的实现类ReferencePipeline中,定义的dropWhile( )方法的实现

 @Override
    public final Stream<P_OUT> dropWhile(Predicate<? super P_OUT> predicate) {
        return WhileOps.makeDropWhileRef(this, predicate);
    }

进入WhileOps的makeDropWhileRef( )方法,构造了一个有状态的内部类Op,重写了opWrapSink( )

static <T> Stream<T> makeDropWhileRef(AbstractPipeline<?, T, ?> upstream,
                                          Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
		//内部类Op继承StatefulOp
        class Op extends ReferencePipeline.StatefulOp<T, T> implements DropWhileOp<T> {
            public Op(AbstractPipeline<?, T, ?> upstream, StreamShape inputShape, int opFlags) {
                super(upstream, inputShape, opFlags);
            }
			......
            @Override
            //重写opWrapSink()
            Sink<T> opWrapSink(int flags, Sink<T> sink) {
                return opWrapSink(sink, false);
            }

            public DropWhileSink<T> opWrapSink(Sink<T> sink, boolean retainAndCountDroppedElements) {
            	//方法内部类OpSink
                class OpSink extends Sink.ChainedReference<T, T> implements DropWhileSink<T> {
                    long dropCount;
                    boolean take;

                    OpSink() {
                        super(sink);
                    }

                    @Override
                    //流中元素处理的方法
                    public void accept(T t) {
                    	//取数据的条件
                        boolean takeElement = take || (take = !predicate.test(t));

                        // If ordered and element is dropped increment index
                        // for possible future truncation
                        if (retainAndCountDroppedElements && !takeElement)
                        	//不符合取数据的条件,丢弃数量增加1
                            dropCount++;

                        // If ordered need to process element, otherwise
                        // skip if element is dropped
                        if (retainAndCountDroppedElements || takeElement)
                        	//符合取数据的条件,执行下行流操作
                            downstream.accept(t);
                    }

                    @Override
                    public long getDropCount() {
                        return dropCount;
                    }
                }
                //返回方法内部类OpSink
                return new OpSink();
            }
        }
        //最外层方法返回Op
        return new Op(upstream, StreamShape.REFERENCE, DROP_FLAGS);
    }

预言型接口predicate是传入的i -> i < 4,

通过accept方法,可以看出取数据的条件时takeElement 为true的时候,

boolean takeElement = take || (take = !predicate.test(t));

符合条件时,predicate.test(t)预言通过,丢弃该元素,take为false;

不符合条件时,predicate.test(t)预言不通过,元素不丢弃,take变为true;

当take变为true后,后续元素不再丢弃,全部进行处理。

总结

dropWhile可以实现一直从流中丢弃元素,直到条件不成立,后续元素不再丢弃。

上一篇:C#委托的介绍(delegate、Action、Func、predicate)


下一篇:2021-07-03 Java语言高级(二)5