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 * Like {@link Stream#iterate(Object, UnaryOperator)} but for IO. 78 * 79 * @param <T> the type of stream elements. 80 * @param seed the initial element. 81 * @param f a function to be applied to the previous element to produce a new element. 82 * @return a new sequential {@code IOStream}. 83 */ iterate(final T seed, final IOUnaryOperator<T> f)84 static <T> IOStream<T> iterate(final T seed, final IOUnaryOperator<T> f) { 85 Objects.requireNonNull(f); 86 final Iterator<T> iterator = new Iterator<T>() { 87 @SuppressWarnings("unchecked") 88 T t = (T) IOStreams.NONE; 89 90 @Override 91 public boolean hasNext() { 92 return true; 93 } 94 95 @Override 96 public T next() { 97 return t = t == IOStreams.NONE ? seed : Erase.apply(f, t); 98 } 99 }; 100 return adapt(StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false)); 101 } 102 103 /** 104 * Null-safe version of {@link StreamSupport#stream(java.util.Spliterator, boolean)}. 105 * 106 * Copied from Apache Commons Lang. 107 * 108 * @param <T> the type of stream elements. 109 * @param values the elements of the new stream, may be {@code null}. 110 * @return the new stream on {@code values} or {@link Stream#empty()}. 111 */ 112 @SuppressWarnings("resource") // call to #empty() of(final Iterable<T> values)113 static <T> IOStream<T> of(final Iterable<T> values) { 114 return values == null ? empty() : adapt(StreamSupport.stream(values.spliterator(), false)); 115 } 116 117 /** 118 * Null-safe version of {@link Stream#of(Object[])} for an IO stream. 119 * 120 * @param <T> the type of stream elements. 121 * @param values the elements of the new stream, may be {@code null}. 122 * @return the new stream on {@code values} or {@link Stream#empty()}. 123 */ 124 @SuppressWarnings("resource") 125 @SafeVarargs // Creating a stream from an array is safe of(final T... values)126 static <T> IOStream<T> of(final T... values) { 127 return values == null || values.length == 0 ? empty() : adapt(Arrays.stream(values)); 128 } 129 130 /** 131 * Returns a sequential {@code IOStreamImpl} containing a single element. 132 * 133 * @param t the single element 134 * @param <T> the type of stream elements 135 * @return a singleton sequential stream 136 */ of(final T t)137 static <T> IOStream<T> of(final T t) { 138 return adapt(Stream.of(t)); 139 } 140 141 /** 142 * Like {@link Stream#allMatch(java.util.function.Predicate)} but throws {@link IOException}. 143 * 144 * @param predicate {@link Stream#allMatch(java.util.function.Predicate)}. 145 * @return Like {@link Stream#allMatch(java.util.function.Predicate)}. 146 * @throws IOException if an I/O error occurs. 147 */ 148 @SuppressWarnings("unused") // thrown by Erase. allMatch(final IOPredicate<? super T> predicate)149 default boolean allMatch(final IOPredicate<? super T> predicate) throws IOException { 150 return unwrap().allMatch(t -> Erase.test(predicate, t)); 151 } 152 153 /** 154 * Like {@link Stream#anyMatch(java.util.function.Predicate)} but throws {@link IOException}. 155 * 156 * @param predicate {@link Stream#anyMatch(java.util.function.Predicate)}. 157 * @return Like {@link Stream#anyMatch(java.util.function.Predicate)}. 158 * @throws IOException if an I/O error occurs. 159 */ 160 @SuppressWarnings("unused") // thrown by Erase. anyMatch(final IOPredicate<? super T> predicate)161 default boolean anyMatch(final IOPredicate<? super T> predicate) throws IOException { 162 return unwrap().anyMatch(t -> Erase.test(predicate, t)); 163 } 164 165 /** 166 * TODO Package-private for now, needs IOCollector? 167 * 168 * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It 169 * would be ideal to have only one. 170 * 171 * Like {@link Stream#collect(Collector)}. 172 * 173 * Package private for now. 174 * 175 * @param <R> Like {@link Stream#collect(Collector)}. 176 * @param <A> Like {@link Stream#collect(Collector)}. 177 * @param collector Like {@link Stream#collect(Collector)}. 178 * @return Like {@link Stream#collect(Collector)}. 179 */ collect(final Collector<? super T, A, R> collector)180 default <R, A> R collect(final Collector<? super T, A, R> collector) { 181 return unwrap().collect(collector); 182 } 183 184 /** 185 * Like 186 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 187 * 188 * @param <R> Like 189 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 190 * @param supplier Like 191 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 192 * @param accumulator Like 193 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 194 * @param combiner Like 195 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 196 * @return Like 197 * {@link Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer)}. 198 * @throws IOException if an I/O error occurs. 199 */ 200 @SuppressWarnings("unused") // thrown by Erase. collect(final IOSupplier<R> supplier, final IOBiConsumer<R, ? super T> accumulator, final IOBiConsumer<R, R> combiner)201 default <R> R collect(final IOSupplier<R> supplier, final IOBiConsumer<R, ? super T> accumulator, final IOBiConsumer<R, R> combiner) throws IOException { 202 return unwrap().collect(() -> Erase.get(supplier), (t, u) -> Erase.accept(accumulator, t, u), (t, u) -> Erase.accept(combiner, t, u)); 203 } 204 205 /** 206 * Like {@link Stream#count()}. 207 * 208 * @return Like {@link Stream#count()}. 209 */ count()210 default long count() { 211 return unwrap().count(); 212 } 213 214 /** 215 * Like {@link Stream#distinct()}. 216 * 217 * @return Like {@link Stream#distinct()}. 218 */ distinct()219 default IOStream<T> distinct() { 220 return adapt(unwrap().distinct()); 221 } 222 223 /** 224 * Like {@link Stream#filter(java.util.function.Predicate)}. 225 * 226 * @param predicate Like {@link Stream#filter(java.util.function.Predicate)}. 227 * @return Like {@link Stream#filter(java.util.function.Predicate)}. 228 * @throws IOException if an I/O error occurs. 229 */ 230 @SuppressWarnings("unused") // thrown by Erase. filter(final IOPredicate<? super T> predicate)231 default IOStream<T> filter(final IOPredicate<? super T> predicate) throws IOException { 232 return adapt(unwrap().filter(t -> Erase.test(predicate, t))); 233 } 234 235 /** 236 * Like {@link Stream#findAny()}. 237 * 238 * @return Like {@link Stream#findAny()}. 239 */ findAny()240 default Optional<T> findAny() { 241 return unwrap().findAny(); 242 } 243 244 /** 245 * Like {@link Stream#findFirst()}. 246 * 247 * @return Like {@link Stream#findFirst()}. 248 */ findFirst()249 default Optional<T> findFirst() { 250 return unwrap().findFirst(); 251 } 252 253 /** 254 * Like {@link Stream#flatMap(java.util.function.Function)}. 255 * 256 * @param <R> Like {@link Stream#flatMap(java.util.function.Function)}. 257 * @param mapper Like {@link Stream#flatMap(java.util.function.Function)}. 258 * @return Like {@link Stream#flatMap(java.util.function.Function)}. 259 * @throws IOException if an I/O error occurs. 260 */ 261 @SuppressWarnings("unused") // thrown by Erase. flatMap(final IOFunction<? super T, ? extends IOStream<? extends R>> mapper)262 default <R> IOStream<R> flatMap(final IOFunction<? super T, ? extends IOStream<? extends R>> mapper) throws IOException { 263 return adapt(unwrap().flatMap(t -> Erase.apply(mapper, t).unwrap())); 264 } 265 266 /** 267 * TODO Package-private for now, needs IODoubleStream? 268 * 269 * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It 270 * would be ideal to have only one. 271 * 272 * Like {@link Stream#flatMapToDouble(java.util.function.Function)}. 273 * 274 * @param mapper Like {@link Stream#flatMapToDouble(java.util.function.Function)}. 275 * @return Like {@link Stream#flatMapToDouble(java.util.function.Function)}. 276 * @throws IOException if an I/O error occurs. 277 */ 278 @SuppressWarnings("unused") // thrown by Erase. flatMapToDouble(final IOFunction<? super T, ? extends DoubleStream> mapper)279 default DoubleStream flatMapToDouble(final IOFunction<? super T, ? extends DoubleStream> mapper) throws IOException { 280 return unwrap().flatMapToDouble(t -> Erase.apply(mapper, t)); 281 } 282 283 /** 284 * TODO Package-private for now, needs IOIntStream? 285 * 286 * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It 287 * would be ideal to have only one. 288 * 289 * Like {@link Stream#flatMapToInt(java.util.function.Function)}. 290 * 291 * @param mapper Like {@link Stream#flatMapToInt(java.util.function.Function)}. 292 * @return Like {@link Stream#flatMapToInt(java.util.function.Function)}. 293 * @throws IOException if an I/O error occurs. 294 */ 295 @SuppressWarnings("unused") // thrown by Erase. flatMapToInt(final IOFunction<? super T, ? extends IntStream> mapper)296 default IntStream flatMapToInt(final IOFunction<? super T, ? extends IntStream> mapper) throws IOException { 297 return unwrap().flatMapToInt(t -> Erase.apply(mapper, t)); 298 } 299 300 /** 301 * TODO Package-private for now, needs IOLongStream? 302 * 303 * Adding this method now and an IO version later is an issue because call sites would have to type-cast to pick one. It 304 * would be ideal to have only one. 305 * 306 * Like {@link Stream#flatMapToLong(java.util.function.Function)}. 307 * 308 * @param mapper Like {@link Stream#flatMapToLong(java.util.function.Function)}. 309 * @return Like {@link Stream#flatMapToLong(java.util.function.Function)}. 310 * @throws IOException if an I/O error occurs. 311 */ 312 @SuppressWarnings("unused") // thrown by Erase. flatMapToLong(final IOFunction<? super T, ? extends LongStream> mapper)313 default LongStream flatMapToLong(final IOFunction<? super T, ? extends LongStream> mapper) throws IOException { 314 return unwrap().flatMapToLong(t -> Erase.apply(mapper, t)); 315 } 316 317 /** 318 * Performs an action for each element gathering any exceptions. 319 * 320 * @param action The action to apply to each element. 321 * @throws IOExceptionList if any I/O errors occur. 322 */ forAll(final IOConsumer<T> action)323 default void forAll(final IOConsumer<T> action) throws IOExceptionList { 324 forAll(action, (i, e) -> e); 325 } 326 327 /** 328 * Performs an action for each element gathering any exceptions. 329 * 330 * @param action The action to apply to each element. 331 * @param exSupplier The exception supplier. 332 * @throws IOExceptionList if any I/O errors occur. 333 */ forAll(final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier)334 default void forAll(final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier) throws IOExceptionList { 335 final AtomicReference<List<IOException>> causeList = new AtomicReference<>(); 336 final AtomicInteger index = new AtomicInteger(); 337 final IOConsumer<T> safeAction = IOStreams.toIOConsumer(action); 338 unwrap().forEach(e -> { 339 try { 340 safeAction.accept(e); 341 } catch (final IOException innerEx) { 342 if (causeList.get() == null) { 343 // Only allocate if required 344 causeList.set(new ArrayList<>()); 345 } 346 if (exSupplier != null) { 347 causeList.get().add(exSupplier.apply(index.get(), innerEx)); 348 } 349 } 350 index.incrementAndGet(); 351 }); 352 IOExceptionList.checkEmpty(causeList.get(), null); 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