目录
前言
在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可以实现一直从流中丢弃元素,直到条件不成立,后续元素不再丢弃。