Returns a {@link Stream} containing the elements of the first stream, followed by the elements of the second stream, and so on. <p>This is equivalent to {@code Stream.of(streams).flatMap(stream -> stream)}, but the returned stream may perform better. @see Stream#concat(Stream, Stream)
(Stream<? extends T>... streams)
| 183 | * @see Stream#concat(Stream, Stream) |
| 184 | */ |
| 185 | @SuppressWarnings("unchecked") // could probably be avoided with a forwarding Spliterator |
| 186 | @SafeVarargs |
| 187 | public static <T extends @Nullable Object> Stream<T> concat(Stream<? extends T>... streams) { |
| 188 | // TODO(lowasser): consider an implementation that can support SUBSIZED |
| 189 | boolean isParallel = false; |
| 190 | int characteristics = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.NONNULL; |
| 191 | long estimatedSize = 0L; |
| 192 | ImmutableList.Builder<Spliterator<? extends T>> splitrsBuilder = |
| 193 | new ImmutableList.Builder<>(streams.length); |
| 194 | for (Stream<? extends T> stream : streams) { |
| 195 | isParallel |= stream.isParallel(); |
| 196 | Spliterator<? extends T> splitr = stream.spliterator(); |
| 197 | splitrsBuilder.add(splitr); |
| 198 | characteristics &= splitr.characteristics(); |
| 199 | estimatedSize = LongMath.saturatedAdd(estimatedSize, splitr.estimateSize()); |
| 200 | } |
| 201 | return StreamSupport.stream( |
| 202 | CollectSpliterators.flatMap( |
| 203 | splitrsBuilder.build().spliterator(), |
| 204 | splitr -> (Spliterator<T>) splitr, |
| 205 | characteristics, |
| 206 | estimatedSize), |
| 207 | isParallel) |
| 208 | .onClose(() -> closeAll(streams)); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Returns an {@link IntStream} containing the elements of the first stream, followed by the |