示例代码:
public static void main(String[] args) {
var is= IntStream.builder()
.add(-20)
.add(13)
.add(-2)
.add(-18)
.build();
System.out.println("is whether the square of any elements is greater than 20:"+finalIs.anyMatch(ele->ele*ele>20));
//System.out.println("is whether the square of all elements is greater than 20:"+finalIs.allMatch(ele->ele*ele>20));
}
在学习Java的Stream的时候,遇到这个代码。由于我之前学习Lambda时候,基础没有很好掌握。因此在此处有些卡住了。
因为,这里的继承有些复杂我一时没找到函数的具体继承链条的关系所以有些懵了。不过最后还是靠着IDE把大概的脉络摸了一遍。这篇文章就是一个思路梳理记录。
首先是IntStream一个继承关系的图示:
以下是我摸索的一个简单的运行流程展示:
首先,引用中对应的
import java.util.stream.IntStream;
具体对应的文件源码是一个 IntStream 接口文件
位置在这里 java.base\java\util\stream\IntStream.class
我们知道单纯的接口文件是无法实现操作的,况且接口中的 anyMatch/allMatch也是没有代码的
/**
* Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not
* necessary for determining the result. If the stream is empty then
* {@code false} is returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
* @apiNote
* This method evaluates the <em>existential quantification</em> of the
* predicate over the elements of the stream (for some x P(x)).
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided
* predicate, otherwise {@code false}
*/
boolean anyMatch(IntPredicate predicate);
/**
* Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for
* determining the result. If the stream is empty then {@code true} is
* returned and the predicate is not evaluated.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
*
* @apiNote
* This method evaluates the <em>universal quantification</em> of the
* predicate over the elements of the stream (for all x P(x)). If the
* stream is empty, the quantification is said to be <em>vacuously
* satisfied</em> and is always {@code true} (regardless of P(x)).
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to elements of this stream
* @return {@code true} if either all elements of the stream match the
* provided predicate or the stream is empty, otherwise {@code false}
*/
boolean allMatch(IntPredicate predicate);
当时这里我就陷入了困惑,并寻找了各种资料。终于在上面那张关系图的指引下。我在 IntPipeline 中找到了对应的实现代码:
@Override
public final boolean anyMatch(IntPredicate predicate) {
return evaluate(MatchOps.makeInt(predicate, MatchOps.MatchKind.ANY));
}
@Override
public final boolean allMatch(IntPredicate predicate) {
return evaluate(MatchOps.makeInt(predicate, MatchOps.MatchKind.ALL));
}
不过,IntStream是怎么继承,引用IntPipeline 的代码的呢?
在一步步的排查之后发现端倪在:
var is= IntStream.builder()
IntStream的builder代码实现是这样的
/**
* Returns a builder for an {@code IntStream}.
*
* @return a stream builder
*/
public static Builder builder() {
return new Streams.IntStreamBuilderImpl();
}
根据代码跳转到:
java.base\java\util\streams
/**
* Constructor for building a stream of 0 or more elements.
*/
IntStreamBuilderImpl() { }
/**
* Constructor for a singleton stream.
*
* @param t the single element
*/
IntStreamBuilderImpl(int t) {
first = t;
count = -2;
}
IntStreamBuilderImpl这个函数看起来在这里起的作用不大,不过继续往下翻阅代码发现
@Override
public IntStream build() {
int c = count;
if (c >= 0) {
// Switch count to negative value signalling the builder is built
count = -count - 1;
// Use this spliterator if 0 or 1 elements, otherwise use
// the spliterator of the spined buffer
return (c < 2) ? StreamSupport.intStream(this, false) : StreamSupport.intStream(buffer.spliterator(), false);
}
throw new IllegalStateException();
}
这个就是关键了,上面也是build 最后构建了这个函数。
顺藤摸瓜,跳转到:
java.base\java\util\stream\StreamSupport.class
/**
* Creates a new sequential or parallel {@code IntStream} from a
* {@code Spliterator.OfInt}.
*
* <p>The spliterator is only traversed, split, or queried for estimated size
* after the terminal operation of the stream pipeline commences.
*
* <p>It is strongly recommended the spliterator report a characteristic of
* {@code IMMUTABLE} or {@code CONCURRENT}, or be
* <a href="../Spliterator.html#binding">late-binding</a>. Otherwise,
* {@link #intStream(java.util.function.Supplier, int, boolean)} should be
* used to reduce the scope of potential interference with the source. See
* <a href="package-summary.html#NonInterference">Non-Interference</a> for
* more details.
*
* @param spliterator a {@code Spliterator.OfInt} describing the stream elements
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
* @return a new sequential or parallel {@code IntStream}
*/
public static IntStream intStream(Spliterator.OfInt spliterator, boolean parallel) {
return new IntPipeline.Head<>(spliterator,
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
其中:
return new IntPipeline.Head<>
完成最终的构建,将接口 IntStream 指引到 IntPipeline上,并实现了anyMatch/allMatch的代码。
此记!