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