1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util.stream; 26 27 /** 28 * An operation in a stream pipeline that takes a stream as input and produces a stream, possibly of a different 29 * type, as output. An intermediate operation has an input type and an output type (and, an associated input 30 * shape and output shape). An intermediate operation also has a set of <em>operation flags</em> that describes 31 * how the operation transforms characteristics of the stream (such as sortedness or size; see 32 * {@link StreamOpFlag}). 33 * 34 * <p>Intermediate operations are implemented in terms of <em>sink transforms</em>; given a {@code Sink} for the 35 * output type of the operation, produce a {@code Sink} for the input type of the operation, which, when fed with 36 * values, has the effect of implementing the desired operation on the input values and feeding them to the output 37 * sink. 38 * 39 * <p>Some intermediate operations are <em>stateful</em>. This means that the sinks they produce as a result of 40 * the above wrapping may maintain state from processing earlier elements. Stateful intermediate operations must 41 * implement the {@link StatefulOp} interface. 42 * 43 * @apiNote 44 * As an example, consider the stream pipeline: 45 * <pre> 46 * int oldestBob = people.stream().filter(p -> p.getFirstName.equals("Bob")).map(p -> p.getAge()).max(); 47 * </pre> 48 * 49 * <p>This pipeline has two intermediate operations, filter and map. The filtering operation has input and output types 50 * of {@code Person} (with input and output shape of {@code REFERENCE}), and the mapping operation has an input 51 * type of {@code Person} and an output type of {@code Integer} (with shape {@code INT_VALUE}.) When we construct 52 * a sink chain, the mapping operation will be asked to transform a {@code Sink.OfInt} which computes the maximum 53 * value into a {@code Sink} which accepts {@code Person} objects, and whose behavior is to take the supplied 54 * {@code Person}, call {@code getAge()} on it, and pass the resulting value to the downstream sink. This sink 55 * transform might be implement as: 56 * 57 * <pre> 58 * new Sink.ChainedReference<U>(sink) { 59 * public void accept(U u) { 60 * downstream.accept(mappingFunction.applyAsInt(u)); 61 * } 62 * } 63 * </pre> 64 * 65 * @param <E_IN> Type of input elements to the operation 66 * @param <E_OUT> Type of output elements to the operation 67 * @see TerminalOp 68 * @see StatefulOp 69 * @since 1.8 70 */ 71 interface IntermediateOp<E_IN, E_OUT> { 72 73 /** 74 * Get the shape of the input type of this operation 75 * @implSpec The default returns {@code StreamShape.REFERENCE} 76 * @return Shape of the input type of this operation 77 */ 78 default StreamShape inputShape() { return StreamShape.REFERENCE; } 79 80 /** 81 * Get the shape of the output type of this operation 82 * @implSpec The default returns {@code StreamShape.REFERENCE} 83 * @return Shape of the output type of this operation 84 */ 85 default StreamShape outputShape() { return StreamShape.REFERENCE; } 86 87 /** 88 * Get the operation flags of this operation. 89 * 90 * @implSpec The default returns {@code 0} 91 * @return a bitmap describing the operation flags of this operation 92 * @see StreamOpFlag 93 */ 94 default int getOpFlags() { return 0; } 95 96 /** 97 * Return whether this operation is stateful or not. If it is stateful, then the method 98 * {@link #evaluateParallel(PipelineHelper)} must be overridden. 99 * 100 * @implSpec The default implementation returns {@code false}. 101 * 102 * @return {@code true} then operation is stateful 103 */ 104 default boolean isStateful() { return false; } 105 106 /** 107 * Accept a {@code Sink} which will receive the results of this operation, and return a {@code Sink} 108 * which accepts elements of the input type of this operation and which performs the operation, passing 109 * the results to the provided {@code Sink}. 110 * 111 * <p>The implementation may use the {@code flags} parameter to optimize the sink wrapping. For example, if 112 * the input is already {@code DISTINCT}, the implementation for the {@code Stream#distinct()} method could 113 * just return the sink it was passed. 114 * 115 * @param flags The combined stream and operation flags up to, but not including, this operation. 116 * @param sink elements will be sent to this sink after the processing. 117 * @return a sink which will accept elements and perform the operation upon 118 * each element, passing the results (if any) to the provided {@code Sink}. 119 */ 120 Sink<E_IN> wrapSink(int flags, Sink<E_OUT> sink); 121 122 /** 123 * Perform a parallel evaluation of the operation using the specified {@code PipelineHelper}, which describes 124 * the stream source and upstream intermediate operations. Only called on stateful operations. 125 * If {@link #isStateful()} returns true then implementations must override the default implementation. 126 * 127 * @implSpec The default implementation throws an {@link UnsupportedOperationException} 128 * 129 * @param helper the pipeline helper 130 * @param <P_IN> the type of elements in the pipeline source 131 * @return a {@code Node} describing the result of the evaluation 132 */ 133 default <P_IN> Node<E_OUT> evaluateParallel(PipelineHelper<P_IN, E_OUT> helper) { 134 throw new UnsupportedOperationException("Parallel evaluation is not supported"); 135 } 136 }