• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.io.function;
19 
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Objects;
26 import java.util.Optional;
27 import java.util.Spliterator;
28 import java.util.Spliterators;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.concurrent.atomic.AtomicReference;
31 import java.util.function.BiFunction;
32 import java.util.function.IntFunction;
33 import java.util.function.ToDoubleFunction;
34 import java.util.function.ToIntFunction;
35 import java.util.function.ToLongFunction;
36 import java.util.function.UnaryOperator;
37 import java.util.stream.Collector;
38 import java.util.stream.DoubleStream;
39 import java.util.stream.IntStream;
40 import java.util.stream.LongStream;
41 import java.util.stream.Stream;
42 import java.util.stream.StreamSupport;
43 
44 import org.apache.commons.io.IOExceptionList;
45 
46 /**
47  * Like {@link Stream} but throws {@link IOException}.
48  *
49  * @param <T> the type of the stream elements.
50  * @since 2.12.0
51  */
52 public interface IOStream<T> extends IOBaseStream<T, IOStream<T>, Stream<T>> {
53 
54     /**
55      * Constructs a new IOStream for the given Stream.
56      *
57      * @param <T> the type of the stream elements.
58      * @param stream The stream to delegate.
59      * @return a new IOStream.
60      */
adapt(final Stream<T> stream)61     static <T> IOStream<T> adapt(final Stream<T> stream) {
62         return IOStreamAdapter.adapt(stream);
63     }
64 
65     /**
66      * This class' version of {@link Stream#empty()}.
67      *
68      * @param <T> the type of the stream elements
69      * @return an empty sequential {@code IOStreamImpl}.
70      * @see Stream#empty()
71      */
empty()72     static <T> IOStream<T> empty() {
73         return IOStreamAdapter.adapt(Stream.empty());
74     }
75 
76     /**
77      * Performs an action for each element gathering any exceptions.
78      *
79      * @param action The action to apply to each element.
80      * @throws IOExceptionList if any I/O errors occur.
81      */
forAll(final IOConsumer<T> action)82     default void forAll(final IOConsumer<T> action) throws IOExceptionList {
83         forAll(action, (i, e) -> e);
84     }
85 
86     /**
87      * Performs an action for each element gathering any exceptions.
88      *
89      * @param action The action to apply to each element.
90      * @param exSupplier The exception supplier.
91      * @throws IOExceptionList if any I/O errors occur.
92      */
forAll(final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier)93     default void forAll(final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier) throws IOExceptionList {
94         final AtomicReference<List<IOException>> causeList = new AtomicReference<>();
95         final AtomicInteger index = new AtomicInteger();
96         final IOConsumer<T> safeAction = IOStreams.toIOConsumer(action);
97         unwrap().forEach(e -> {
98             try {
99                 safeAction.accept(e);
100             } catch (final IOException innerEx) {
101                 if (causeList.get() == null) {
102                     // Only allocate if required
103                     causeList.set(new ArrayList<>());
104                 }
105                 if (exSupplier != null) {
106                     causeList.get().add(exSupplier.apply(index.get(), innerEx));
107                 }
108             }
109             index.incrementAndGet();
110         });
111         IOExceptionList.checkEmpty(causeList.get(), null);
112     }
113 
114     /**
115      * Like {@link Stream#iterate(Object, UnaryOperator)} but for IO.
116      *
117      * @param <T> the type of stream elements.
118      * @param seed the initial element.
119      * @param f a function to be applied to the previous element to produce a new element.
120      * @return a new sequential {@code IOStream}.
121      */
iterate(final T seed, final IOUnaryOperator<T> f)122     static <T> IOStream<T> iterate(final T seed, final IOUnaryOperator<T> f) {
123         Objects.requireNonNull(f);
124         final Iterator<T> iterator = new Iterator<T>() {
125             @SuppressWarnings("unchecked")
126             T t = (T) IOStreams.NONE;
127 
128             @Override
129             public boolean hasNext() {
130                 return true;
131             }
132 
133             @Override
134             public T next() {
135                 return t = t == IOStreams.NONE ? seed : Erase.apply(f, t);
136             }
137         };
138         return adapt(StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false));
139     }
140 
141     /**
142      * Null-safe version of {@link StreamSupport#stream(java.util.Spliterator, boolean)}.
143      *
144      * Copied from Apache Commons Lang.
145      *
146      * @param <T> the type of stream elements.
147      * @param values the elements of the new stream, may be {@code null}.
148      * @return the new stream on {@code values} or {@link Stream#empty()}.
149      */
150     @SuppressWarnings("resource") // call to #empty()
of(final Iterable<T> values)151     static <T> IOStream<T> of(final Iterable<T> values) {
152         return values == null ? empty() : adapt(StreamSupport.stream(values.spliterator(), false));
153     }
154 
155     /**
156      * Null-safe version of {@link Stream#of(Object[])} for an IO stream.
157      *
158      * @param <T> the type of stream elements.
159      * @param values the elements of the new stream, may be {@code null}.
160      * @return the new stream on {@code values} or {@link Stream#empty()}.
161      */
162     @SuppressWarnings("resource")
163     @SafeVarargs // Creating a stream from an array is safe
of(final T... values)164     static <T> IOStream<T> of(final T... values) {
165         return values == null || values.length == 0 ? empty() : adapt(Arrays.stream(values));
166     }
167 
168     /**
169      * Returns a sequential {@code IOStreamImpl} containing a single element.
170      *
171      * @param t the single element
172      * @param <T> the type of stream elements
173      * @return a singleton sequential stream
174      */
of(final T t)175     static <T> IOStream<T> of(final T t) {
176         return adapt(Stream.of(t));
177     }
178 
179     /**
180      * Like {@link Stream#allMatch(java.util.function.Predicate)} but throws {@link IOException}.
181      *
182      * @param predicate {@link Stream#allMatch(java.util.function.Predicate)}.
183      * @return Like {@link Stream#allMatch(java.util.function.Predicate)}.
184      * @throws IOException if an I/O error occurs.
185      */
186     @SuppressWarnings("unused") // thrown by Erase.
allMatch(final IOPredicate<? super T> predicate)187     default boolean allMatch(final IOPredicate<? super T> predicate) throws IOException {
188         return unwrap().allMatch(t -> Erase.test(predicate, t));
189     }
190 
191     /**
192      * Like {@link Stream#anyMatch(java.util.function.Predicate)} but throws {@link IOException}.
193      *
194      * @param predicate {@link Stream#anyMatch(java.util.function.Predicate)}.
195      * @return Like {@link Stream#anyMatch(java.util.function.Predicate)}.
196      * @throws IOException if an I/O error occurs.
197      */
198     @SuppressWarnings("unused") // thrown by Erase.
anyMatch(final IOPredicate<? super T> predicate)199     default boolean anyMatch(final IOPredicate<? super T> predicate) throws IOException {
200         return unwrap().anyMatch(t -> Erase.test(predicate, t));
201     }
202 
203     /**
204      * TODO Package-private for now, needs IOCollector?
205      *
206      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
207      * would be ideal to have only one.
208      *
209      * Like {@link Stream#collect(Collector)}.
210      *
211      * Package private for now.
212      *
213      * @param <R> Like {@link Stream#collect(Collector)}.
214      * @param <A> Like {@link Stream#collect(Collector)}.
215      * @param collector Like {@link Stream#collect(Collector)}.
216      * @return Like {@link Stream#collect(Collector)}.
217      */
collect(final Collector<? super T, A, R> collector)218     default <R, A> R collect(final Collector<? super T, A, R> collector) {
219         return unwrap().collect(collector);
220     }
221 
222     /**
223      * Like
224      * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
225      *
226      * @param <R> Like
227      *        {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
228      * @param supplier Like
229      *        {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
230      * @param accumulator Like
231      *        {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
232      * @param combiner Like
233      *        {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
234      * @return Like
235      *         {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}.
236      * @throws IOException if an I/O error occurs.
237      */
238     @SuppressWarnings("unused") // thrown by Erase.
collect(final IOSupplier<R> supplier, final IOBiConsumer<R, ? super T> accumulator, final IOBiConsumer<R, R> combiner)239     default <R> R collect(final IOSupplier<R> supplier, final IOBiConsumer<R, ? super T> accumulator, final IOBiConsumer<R, R> combiner) throws IOException {
240         return unwrap().collect(() -> Erase.get(supplier), (t, u) -> Erase.accept(accumulator, t, u), (t, u) -> Erase.accept(combiner, t, u));
241     }
242 
243     /**
244      * Like {@link Stream#count()}.
245      *
246      * @return Like {@link Stream#count()}.
247      */
count()248     default long count() {
249         return unwrap().count();
250     }
251 
252     /**
253      * Like {@link Stream#distinct()}.
254      *
255      * @return Like {@link Stream#distinct()}.
256      */
distinct()257     default IOStream<T> distinct() {
258         return adapt(unwrap().distinct());
259     }
260 
261     /**
262      * Like {@link Stream#filter(java.util.function.Predicate)}.
263      *
264      * @param predicate Like {@link Stream#filter(java.util.function.Predicate)}.
265      * @return Like {@link Stream#filter(java.util.function.Predicate)}.
266      * @throws IOException if an I/O error occurs.
267      */
268     @SuppressWarnings("unused") // thrown by Erase.
filter(final IOPredicate<? super T> predicate)269     default IOStream<T> filter(final IOPredicate<? super T> predicate) throws IOException {
270         return adapt(unwrap().filter(t -> Erase.test(predicate, t)));
271     }
272 
273     /**
274      * Like {@link Stream#findAny()}.
275      *
276      * @return Like {@link Stream#findAny()}.
277      */
findAny()278     default Optional<T> findAny() {
279         return unwrap().findAny();
280     }
281 
282     /**
283      * Like {@link Stream#findFirst()}.
284      *
285      * @return Like {@link Stream#findFirst()}.
286      */
findFirst()287     default Optional<T> findFirst() {
288         return unwrap().findFirst();
289     }
290 
291     /**
292      * Like {@link Stream#flatMap(java.util.function.Function)}.
293      *
294      * @param <R> Like {@link Stream#flatMap(java.util.function.Function)}.
295      * @param mapper Like {@link Stream#flatMap(java.util.function.Function)}.
296      * @return Like {@link Stream#flatMap(java.util.function.Function)}.
297      * @throws IOException if an I/O error occurs.
298      */
299     @SuppressWarnings("unused") // thrown by Erase.
flatMap(final IOFunction<? super T, ? extends IOStream<? extends R>> mapper)300     default <R> IOStream<R> flatMap(final IOFunction<? super T, ? extends IOStream<? extends R>> mapper) throws IOException {
301         return adapt(unwrap().flatMap(t -> Erase.apply(mapper, t).unwrap()));
302     }
303 
304     /**
305      * TODO Package-private for now, needs IODoubleStream?
306      *
307      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
308      * would be ideal to have only one.
309      *
310      * Like {@link Stream#flatMapToDouble(java.util.function.Function)}.
311      *
312      * @param mapper Like {@link Stream#flatMapToDouble(java.util.function.Function)}.
313      * @return Like {@link Stream#flatMapToDouble(java.util.function.Function)}.
314      * @throws IOException if an I/O error occurs.
315      */
316     @SuppressWarnings("unused") // thrown by Erase.
flatMapToDouble(final IOFunction<? super T, ? extends DoubleStream> mapper)317     default DoubleStream flatMapToDouble(final IOFunction<? super T, ? extends DoubleStream> mapper) throws IOException {
318         return unwrap().flatMapToDouble(t -> Erase.apply(mapper, t));
319     }
320 
321     /**
322      * TODO Package-private for now, needs IOIntStream?
323      *
324      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
325      * would be ideal to have only one.
326      *
327      * Like {@link Stream#flatMapToInt(java.util.function.Function)}.
328      *
329      * @param mapper Like {@link Stream#flatMapToInt(java.util.function.Function)}.
330      * @return Like {@link Stream#flatMapToInt(java.util.function.Function)}.
331      * @throws IOException if an I/O error occurs.
332      */
333     @SuppressWarnings("unused") // thrown by Erase.
flatMapToInt(final IOFunction<? super T, ? extends IntStream> mapper)334     default IntStream flatMapToInt(final IOFunction<? super T, ? extends IntStream> mapper) throws IOException {
335         return unwrap().flatMapToInt(t -> Erase.apply(mapper, t));
336     }
337 
338     /**
339      * TODO Package-private for now, needs IOLongStream?
340      *
341      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
342      * would be ideal to have only one.
343      *
344      * Like {@link Stream#flatMapToLong(java.util.function.Function)}.
345      *
346      * @param mapper Like {@link Stream#flatMapToLong(java.util.function.Function)}.
347      * @return Like {@link Stream#flatMapToLong(java.util.function.Function)}.
348      * @throws IOException if an I/O error occurs.
349      */
350     @SuppressWarnings("unused") // thrown by Erase.
flatMapToLong(final IOFunction<? super T, ? extends LongStream> mapper)351     default LongStream flatMapToLong(final IOFunction<? super T, ? extends LongStream> mapper) throws IOException {
352         return unwrap().flatMapToLong(t -> Erase.apply(mapper, t));
353     }
354 
355     /**
356      * Like {@link Stream#forEach(java.util.function.Consumer)} but throws {@link IOException}.
357      *
358      * @param action Like {@link Stream#forEach(java.util.function.Consumer)}.
359      * @throws IOException if an I/O error occurs.
360      */
361     @SuppressWarnings("unused") // thrown by Erase.
forEach(final IOConsumer<? super T> action)362     default void forEach(final IOConsumer<? super T> action) throws IOException {
363         unwrap().forEach(e -> Erase.accept(action, e));
364     }
365 
366     /**
367      * Like {@link Stream#forEachOrdered(java.util.function.Consumer)}.
368      *
369      * @param action Like {@link Stream#forEachOrdered(java.util.function.Consumer)}.
370      * @throws IOException if an I/O error occurs.
371      */
372     @SuppressWarnings("unused") // thrown by Erase.
forEachOrdered(final IOConsumer<? super T> action)373     default void forEachOrdered(final IOConsumer<? super T> action) throws IOException {
374         unwrap().forEachOrdered(e -> Erase.accept(action, e));
375     }
376 
377     /**
378      * Like {@link Stream#limit(long)}.
379      *
380      * @param maxSize Like {@link Stream#limit(long)}.
381      * @return Like {@link Stream#limit(long)}.
382      */
limit(final long maxSize)383     default IOStream<T> limit(final long maxSize) {
384         return adapt(unwrap().limit(maxSize));
385     }
386 
387     /**
388      * Like {@link Stream#map(java.util.function.Function)}.
389      *
390      * @param <R> Like {@link Stream#map(java.util.function.Function)}.
391      * @param mapper Like {@link Stream#map(java.util.function.Function)}.
392      * @return Like {@link Stream#map(java.util.function.Function)}.
393      * @throws IOException if an I/O error occurs.
394      */
395     @SuppressWarnings("unused") // thrown by Erase.
map(final IOFunction<? super T, ? extends R> mapper)396     default <R> IOStream<R> map(final IOFunction<? super T, ? extends R> mapper) throws IOException {
397         return adapt(unwrap().map(t -> Erase.apply(mapper, t)));
398     }
399 
400     /**
401      * TODO Package-private for now, needs IOToDoubleFunction?
402      *
403      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
404      * would be ideal to have only one.
405      *
406      * Like {@link Stream#mapToDouble(ToDoubleFunction)}.
407      *
408      * Package private for now.
409      *
410      * @param mapper Like {@link Stream#mapToDouble(ToDoubleFunction)}.
411      * @return Like {@link Stream#mapToDouble(ToDoubleFunction)}.
412      */
mapToDouble(final ToDoubleFunction<? super T> mapper)413     default DoubleStream mapToDouble(final ToDoubleFunction<? super T> mapper) {
414         return unwrap().mapToDouble(mapper);
415     }
416 
417     /**
418      * TODO Package-private for now, needs IOToIntFunction?
419      *
420      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
421      * would be ideal to have only one.
422      *
423      * Like {@link Stream#mapToInt(ToIntFunction)}.
424      *
425      * Package private for now.
426      *
427      * @param mapper Like {@link Stream#mapToInt(ToIntFunction)}.
428      * @return Like {@link Stream#mapToInt(ToIntFunction)}.
429      */
mapToInt(final ToIntFunction<? super T> mapper)430     default IntStream mapToInt(final ToIntFunction<? super T> mapper) {
431         return unwrap().mapToInt(mapper);
432     }
433 
434     /**
435      * TODO Package-private for now, needs IOToLongFunction?
436      *
437      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
438      * would be ideal to have only one.
439      *
440      * Like {@link Stream#mapToLong(ToLongFunction)}.
441      *
442      * Package private for now.
443      *
444      * @param mapper Like {@link Stream#mapToLong(ToLongFunction)}.
445      * @return Like {@link Stream#mapToLong(ToLongFunction)}.
446      */
mapToLong(final ToLongFunction<? super T> mapper)447     default LongStream mapToLong(final ToLongFunction<? super T> mapper) {
448         return unwrap().mapToLong(mapper);
449     }
450 
451     /**
452      * Like {@link Stream#max(java.util.Comparator)}.
453      *
454      * @param comparator Like {@link Stream#max(java.util.Comparator)}.
455      * @return Like {@link Stream#max(java.util.Comparator)}.
456      * @throws IOException if an I/O error occurs.
457      */
458     @SuppressWarnings("unused") // thrown by Erase.
max(final IOComparator<? super T> comparator)459     default Optional<T> max(final IOComparator<? super T> comparator) throws IOException {
460         return unwrap().max((t, u) -> Erase.compare(comparator, t, u));
461     }
462 
463     /**
464      * Like {@link Stream#min(java.util.Comparator)}.
465      *
466      * @param comparator Like {@link Stream#min(java.util.Comparator)}.
467      * @return Like {@link Stream#min(java.util.Comparator)}.
468      * @throws IOException if an I/O error occurs.
469      */
470     @SuppressWarnings("unused") // thrown by Erase.
min(final IOComparator<? super T> comparator)471     default Optional<T> min(final IOComparator<? super T> comparator) throws IOException {
472         return unwrap().min((t, u) -> Erase.compare(comparator, t, u));
473     }
474 
475     /**
476      * Like {@link Stream#noneMatch(java.util.function.Predicate)}.
477      *
478      * @param predicate Like {@link Stream#noneMatch(java.util.function.Predicate)}.
479      * @return Like {@link Stream#noneMatch(java.util.function.Predicate)}.
480      * @throws IOException if an I/O error occurs.
481      */
482     @SuppressWarnings("unused") // thrown by Erase.
noneMatch(final IOPredicate<? super T> predicate)483     default boolean noneMatch(final IOPredicate<? super T> predicate) throws IOException {
484         return unwrap().noneMatch(t -> Erase.test(predicate, t));
485     }
486 
487     /**
488      * Like {@link Stream#peek(java.util.function.Consumer)}.
489      *
490      * @param action Like {@link Stream#peek(java.util.function.Consumer)}.
491      * @return Like {@link Stream#peek(java.util.function.Consumer)}.
492      * @throws IOException if an I/O error occurs.
493      */
494     @SuppressWarnings("unused") // thrown by Erase.
peek(final IOConsumer<? super T> action)495     default IOStream<T> peek(final IOConsumer<? super T> action) throws IOException {
496         return adapt(unwrap().peek(t -> Erase.accept(action, t)));
497     }
498 
499     /**
500      * Like {@link Stream#reduce(java.util.function.BinaryOperator)}.
501      *
502      * @param accumulator Like {@link Stream#reduce(java.util.function.BinaryOperator)}.
503      * @return Like {@link Stream#reduce(java.util.function.BinaryOperator)}.
504      * @throws IOException if an I/O error occurs.
505      */
506     @SuppressWarnings("unused") // thrown by Erase.
reduce(final IOBinaryOperator<T> accumulator)507     default Optional<T> reduce(final IOBinaryOperator<T> accumulator) throws IOException {
508         return unwrap().reduce((t, u) -> Erase.apply(accumulator, t, u));
509     }
510 
511     /**
512      * Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}.
513      *
514      * @param identity Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}.
515      * @param accumulator Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}.
516      * @return Like {@link Stream#reduce(Object, java.util.function.BinaryOperator)}.
517      * @throws IOException if an I/O error occurs.
518      */
519     @SuppressWarnings("unused") // thrown by Erase.
reduce(final T identity, final IOBinaryOperator<T> accumulator)520     default T reduce(final T identity, final IOBinaryOperator<T> accumulator) throws IOException {
521         return unwrap().reduce(identity, (t, u) -> Erase.apply(accumulator, t, u));
522     }
523 
524     /**
525      * Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
526      *
527      * @param <U> Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
528      * @param identity Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
529      * @param accumulator Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
530      * @param combiner Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
531      * @return Like {@link Stream#reduce(Object, BiFunction, java.util.function.BinaryOperator)}.
532      * @throws IOException if an I/O error occurs.
533      */
534     @SuppressWarnings("unused") // thrown by Erase.
reduce(final U identity, final IOBiFunction<U, ? super T, U> accumulator, final IOBinaryOperator<U> combiner)535     default <U> U reduce(final U identity, final IOBiFunction<U, ? super T, U> accumulator, final IOBinaryOperator<U> combiner) throws IOException {
536         return unwrap().reduce(identity, (t, u) -> Erase.apply(accumulator, t, u), (t, u) -> Erase.apply(combiner, t, u));
537     }
538 
539     /**
540      * Like {@link Stream#skip(long)}.
541      *
542      * @param n Like {@link Stream#skip(long)}.
543      * @return Like {@link Stream#skip(long)}.
544      */
skip(final long n)545     default IOStream<T> skip(final long n) {
546         return adapt(unwrap().skip(n));
547     }
548 
549     /**
550      * Like {@link Stream#sorted()}.
551      *
552      * @return Like {@link Stream#sorted()}.
553      */
sorted()554     default IOStream<T> sorted() {
555         return adapt(unwrap().sorted());
556     }
557 
558     /**
559      * Like {@link Stream#sorted(java.util.Comparator)}.
560      *
561      * @param comparator Like {@link Stream#sorted(java.util.Comparator)}.
562      * @return Like {@link Stream#sorted(java.util.Comparator)}.
563      * @throws IOException if an I/O error occurs.
564      */
565     @SuppressWarnings("unused") // thrown by Erase.
sorted(final IOComparator<? super T> comparator)566     default IOStream<T> sorted(final IOComparator<? super T> comparator) throws IOException {
567         return adapt(unwrap().sorted((t, u) -> Erase.compare(comparator, t, u)));
568     }
569 
570     /**
571      * Like {@link Stream#toArray()}.
572      *
573      * @return {@link Stream#toArray()}.
574      */
toArray()575     default Object[] toArray() {
576         return unwrap().toArray();
577     }
578 
579     /**
580      * TODO Package-private for now, needs IOIntFunction?
581      *
582      * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It
583      * would be ideal to have only one.
584      *
585      * Like {@link Stream#toArray(IntFunction)}.
586      *
587      * Package private for now.
588      *
589      * @param <A> Like {@link Stream#toArray(IntFunction)}.
590      * @param generator Like {@link Stream#toArray(IntFunction)}.
591      * @return Like {@link Stream#toArray(IntFunction)}.
592      */
toArray(final IntFunction<A[]> generator)593     default <A> A[] toArray(final IntFunction<A[]> generator) {
594         return unwrap().toArray(generator);
595     }
596 
597 }
598