33
33
import java .util .Spliterator ;
34
34
import java .util .Spliterators ;
35
35
import java .util .Spliterators .AbstractSpliterator ;
36
+ import java .util .function .BiConsumer ;
36
37
import java .util .function .BiFunction ;
37
38
import java .util .function .Consumer ;
38
39
import java .util .function .DoubleConsumer ;
@@ -205,7 +206,7 @@ public static DoubleStream concat(DoubleStream... streams) {
205
206
}
206
207
207
208
/**
208
- * Returns a stream in which each element is the result of passing the corresponding element of
209
+ * Returns a stream in which each element is the result of passing the corresponding elementY of
209
210
* each of {@code streamA} and {@code streamB} to {@code function}.
210
211
*
211
212
* <p>For example:
@@ -222,7 +223,10 @@ public static DoubleStream concat(DoubleStream... streams) {
222
223
* <p>The resulting stream will only be as long as the shorter of the two input streams; if one
223
224
* stream is longer, its extra elements will be ignored.
224
225
*
225
- * <p>The resulting stream is not <a
226
+ * <p>Note that if you are calling {@link Stream#forEach} on the resulting stream, you might want
227
+ * to consider using {@link #forEachPair} instead of this method.
228
+ *
229
+ * <p><b>Performance note:</b> The resulting stream is not <a
226
230
* href="http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html">efficiently splittable</a>.
227
231
* This may harm parallel performance.
228
232
*/
@@ -255,6 +259,59 @@ public boolean tryAdvance(Consumer<? super R> action) {
255
259
isParallel );
256
260
}
257
261
262
+ /**
263
+ * Invokes {@code consumer} once for each pair of <i>corresponding</i> elements in {@code streamA}
264
+ * and {@code streamB}. If one stream is longer than the other, the extra elements are silently
265
+ * ignored. Elements passed to the consumer are guaranteed to come from the same position in their
266
+ * respective source streams. For example:
267
+ *
268
+ * <pre>{@code
269
+ * Streams.forEachPair(
270
+ * Stream.of("foo1", "foo2", "foo3"),
271
+ * Stream.of("bar1", "bar2"),
272
+ * (arg1, arg2) -> System.out.println(arg1 + ":" + arg2)
273
+ * }</pre>
274
+ *
275
+ * <p>will print:
276
+ *
277
+ * <pre>{@code
278
+ * foo1:bar1
279
+ * foo2:bar2
280
+ * }</pre>
281
+ *
282
+ * <p><b>Warning:</b> If either supplied stream is a parallel stream, the same correspondence
283
+ * between elements will be made, but the order in which those pairs of elements are passed to the
284
+ * consumer is <i>not</i> defined.
285
+ *
286
+ * <p>Note that many usages of this method can be replaced with simpler calls to {@link #zip}.
287
+ * This method behaves equivalently to {@linkplain #zip zipping} the stream elements into
288
+ * temporary pair objects and then using {@link Stream#forEach} on that stream.
289
+ */
290
+ public static <A , B > void forEachPair (
291
+ Stream <A > streamA , Stream <B > streamB , BiConsumer <? super A , ? super B > consumer ) {
292
+ checkNotNull (consumer );
293
+
294
+ if (streamA .isParallel () || streamB .isParallel ()) {
295
+ zip (streamA , streamB , TemporaryPair ::new ).forEach (pair -> consumer .accept (pair .a , pair .b ));
296
+ } else {
297
+ Iterator <A > iterA = streamA .iterator ();
298
+ Iterator <B > iterB = streamB .iterator ();
299
+ while (iterA .hasNext () && iterB .hasNext ()) {
300
+ consumer .accept (iterA .next (), iterB .next ());
301
+ }
302
+ }
303
+ }
304
+
305
+ private static class TemporaryPair <A , B > {
306
+ final A a ;
307
+ final B b ;
308
+
309
+ TemporaryPair (A a , B b ) {
310
+ this .a = a ;
311
+ this .b = b ;
312
+ }
313
+ }
314
+
258
315
/**
259
316
* Returns a stream consisting of the results of applying the given function to the elements of
260
317
* {@code stream} and their indices in the stream. For example,
0 commit comments