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