在Java的Stream API中,map
方法是用于对流中的每个元素进行映射操作的重要方法。本文将深入解析map
方法的源码,探讨其内部实现和机制。
首先,让我们看一下Stream
接口中map
方法的声明:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
这个方法接受一个Function
参数,用于定义元素的映射规则。Function
是一个函数式接口,其apply
方法将元素映射为新的值。
map
方法的实现同样是在BaseStream
接口中定义的。以下是BaseStream
接口中关于map
方法的默认实现:
default <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return (Stream<R>) (isParallel()
? new ReferencePipeline.Head<>(this, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, null, OpMap.makeRef(mapper), StreamShape.REFERENCE)
: new ReferencePipeline.Head<>(this, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT, null, OpMap.makeRef(mapper)));
}
解析这段代码:
Objects.requireNonNull(mapper);
:确保传入的mapper
不为null
,否则抛出NullPointerException
。isParallel()
:检查流是否为并行流。new ReferencePipeline.Head<>
:创建一个新的ReferencePipeline.Head
对象,表示流的头部操作。如果流是并行的,会传入额外的参数 StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT
和 StreamShape.REFERENCE
。OpMap.makeRef(mapper)
:创建一个表示映射操作的OpMap
对象,并将mapper
传递给它。OpMap
类是Stream
操作的内部实现之一,用于表示映射操作。以下是关键部分的源码:
final class OpMap<T, U> implements ReferencePipeline.StatefulOp<T, U>, OpMapFactory<T, U> {
// ...
@Override
public <S> Node<U> opEvaluateParallel(PipelineHelper<U> helper, Spliterator<S> spliterator, IntFunction<U[]> generator) {
return Nodes.map(helper, spliterator, true, generator);
}
// ...
}
这段代码展示了OpMap
类的一部分实现。它包含一个opEvaluateParallel
方法,用于在并行流中进行映射操作。在这里,它调用了Nodes.map
方法,这个方法会根据给定的Spliterator
在并行环境中执行映射操作。
List<String> stringList = Arrays.asList("apple", "banana", "orange", "grape", "watermelon");
Stream<Integer> lengthStream = stringList.stream()
.map(String::length);
lengthStream.forEach(System.out::println);
在这个例子中,我们使用map
方法将每个字符串映射为其长度。在实际执行中,map
方法会根据传入的Function
对流中的元素进行映射,并返回一个新的流。在内部,它会创建一个新的OpMap
操作来表示这个映射操作。