在Java的Stream API中,filter
方法是用于过滤流中元素的关键操作之一。本文将深入解析filter
方法的源码,理解其内部实现和机制。
首先,让我们看一下Stream
接口中filter
方法的声明:
Stream<T> filter(Predicate<? super T> predicate);
这个方法接受一个Predicate
参数,用于定义过滤条件。Predicate
是一个函数式接口,其test
方法返回boolean
值。
filter
方法的实现实际上是在BaseStream
接口中定义的。以下是BaseStream
接口中关于filter
方法的默认实现:
default Stream<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
return (Stream<T>) (isParallel()
? new ReferencePipeline.Head<>(this, StreamOpFlag.NOT_SIZED, null, OpFilter.makeRef(predicate), Shape.UNKNOWN_SIZE)
: new ReferencePipeline.Head<>(this, StreamOpFlag.NOT_SIZED, null, OpFilter.makeRef(predicate)));
}
解析这段代码:
Objects.requireNonNull(predicate);
:确保传入的predicate
不为null
,否则抛出NullPointerException
。isParallel()
:检查流是否为并行流。new ReferencePipeline.Head<>
:创建一个新的ReferencePipeline.Head
对象,表示流的头部操作。如果流是并行的,会传入额外的参数 StreamOpFlag.NOT_SIZED
和 Shape.UNKNOWN_SIZE
。OpFilter.makeRef(predicate)
:创建一个表示过滤操作的OpFilter
对象,并将predicate
传递给它。OpFilter
类是Stream
操作的内部实现之一,用于表示过滤操作。以下是关键部分的源码:
final class OpFilter<T> implements ReferencePipeline.StatefulOp<T, T>, OpFilterFactory<T, T> {
// ...
static <T> StreamShape<T> toStreamShape(boolean notKnown) {
return notKnown ? StreamShape.REFERENCE : StreamShape.SIZED;
}
@Override
public <S> Node<T> opEvaluateParallel(PipelineHelper<T> helper, Spliterator<S> spliterator, IntFunction<T[]> generator) {
return Nodes.filter(helper, spliterator, true, generator);
}
// ...
}
这段代码展示了OpFilter
类的一部分实现。它包含一个opEvaluateParallel
方法,用于在并行流中进行过滤操作。在这里,它调用了Nodes.filter
方法,这个方法会根据给定的Spliterator
在并行环境中执行过滤操作。
List<String> stringList = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Stream<String> filteredStream = stringList.stream()
.filter(s -> s.length() > 5);
filteredStream.forEach(System.out::println);
在这个例子中,我们使用filter
方法过滤了长度大于5的字符串。在实际执行中,filter
方法会根据传入的Predicate
对流进行过滤,并返回一个新的流。在内部,它会创建一个新的OpFilter
操作来表示这个过滤操作。