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 package org.apache.commons.collections4; 18 19 import java.util.ArrayList; 20 import java.util.Collection; 21 import java.util.Collections; 22 import java.util.Comparator; 23 import java.util.HashSet; 24 import java.util.Iterator; 25 import java.util.LinkedHashSet; 26 import java.util.List; 27 import java.util.Objects; 28 import java.util.Set; 29 30 import org.apache.commons.collections4.functors.EqualPredicate; 31 import org.apache.commons.collections4.iterators.LazyIteratorChain; 32 import org.apache.commons.collections4.iterators.ReverseListIterator; 33 import org.apache.commons.collections4.iterators.UniqueFilterIterator; 34 35 /** 36 * Provides utility methods and decorators for {@link Iterable} instances. 37 * <p> 38 * <strong>Note</strong>: This utility class has been designed with fail-fast argument checking. 39 * </p> 40 * <ul> 41 * <li>All decorator methods are <em>not</em> null-safe for the provided Iterable argument; for example, they will throw a {@link NullPointerException} if a 42 * null Iterable is passed as argument. 43 * <li>All other utility methods are null-safe for the provided Iterable argument; for example, they will treat a null Iterable the same way as an empty one. 44 * For other arguments which are null, a {@link Predicate} will result in a {@link NullPointerException}. Exception: passing a null {@link Comparator} is 45 * equivalent to a Comparator with natural ordering. 46 * </ul> 47 * 48 * @since 4.1 49 */ 50 public class IterableUtils { 51 52 /** 53 * Inner class to distinguish unmodifiable instances. 54 */ 55 private static final class UnmodifiableIterable<E> extends FluentIterable<E> { 56 private final Iterable<E> iterable; 57 58 UnmodifiableIterable(final Iterable<E> iterable) { 59 this.iterable = iterable; 60 } 61 62 @Override 63 public Iterator<E> iterator() { 64 return IteratorUtils.unmodifiableIterator(iterable.iterator()); 65 } 66 } 67 68 /** 69 * An empty iterable. 70 */ 71 @SuppressWarnings("rawtypes") 72 static final FluentIterable EMPTY_ITERABLE = new FluentIterable<Object>() { 73 @Override 74 public Iterator<Object> iterator() { 75 return IteratorUtils.emptyIterator(); 76 } 77 }; 78 79 /** 80 * Returns a view of the given iterable that contains at most the given number 81 * of elements. 82 * <p> 83 * The returned iterable's iterator supports {@code remove()} when the corresponding 84 * input iterator supports it. 85 * </p> 86 * 87 * @param <E> the element type 88 * @param iterable the iterable to limit, may not be null 89 * @param maxSize the maximum number of elements, must not be negative 90 * @return a bounded view on the specified iterable 91 * @throws IllegalArgumentException if maxSize is negative 92 * @throws NullPointerException if iterable is null 93 */ 94 public static <E> Iterable<E> boundedIterable(final Iterable<E> iterable, final long maxSize) { 95 Objects.requireNonNull(iterable, "iterable"); 96 if (maxSize < 0) { 97 throw new IllegalArgumentException("MaxSize parameter must not be negative."); 98 } 99 100 return new FluentIterable<E>() { 101 @Override 102 public Iterator<E> iterator() { 103 return IteratorUtils.boundedIterator(iterable.iterator(), maxSize); 104 } 105 }; 106 } 107 108 /** 109 * Combines the provided iterables into a single iterable. 110 * <p> 111 * The returned iterable has an iterator that traverses the elements in the order 112 * of the arguments, i.e. iterables[0], iterables[1], .... The source iterators 113 * are not polled until necessary. 114 * </p> 115 * <p> 116 * The returned iterable's iterator supports {@code remove()} when the corresponding 117 * input iterator supports it. 118 * </p> 119 * 120 * @param <E> the element type 121 * @param iterables the iterables to combine, may not be null 122 * @return a new iterable, combining the provided iterables 123 * @throws NullPointerException if either of the provided iterables is null 124 */ 125 public static <E> Iterable<E> chainedIterable(final Iterable<? extends E>... iterables) { 126 checkNotNull(iterables); 127 return new FluentIterable<E>() { 128 @Override 129 public Iterator<E> iterator() { 130 return new LazyIteratorChain<E>() { 131 @Override 132 protected Iterator<? extends E> nextIterator(final int count) { 133 if (count > iterables.length) { 134 return null; 135 } 136 return iterables[count - 1].iterator(); 137 } 138 }; 139 } 140 }; 141 } 142 143 /** 144 * Combines two iterables into a single iterable. 145 * <p> 146 * The returned iterable has an iterator that traverses the elements in {@code a}, 147 * followed by the elements in {@code b}. The source iterators are not polled until 148 * necessary. 149 * </p> 150 * <p> 151 * The returned iterable's iterator supports {@code remove()} when the corresponding 152 * input iterator supports it. 153 * </p> 154 * 155 * @param <E> the element type 156 * @param a the first iterable, may not be null 157 * @param b the second iterable, may not be null 158 * @return a new iterable, combining the provided iterables 159 * @throws NullPointerException if either a or b is null 160 */ 161 @SuppressWarnings("unchecked") 162 public static <E> Iterable<E> chainedIterable(final Iterable<? extends E> a, 163 final Iterable<? extends E> b) { 164 return chainedIterable(new Iterable[] {a, b}); 165 } 166 167 /** 168 * Combines three iterables into a single iterable. 169 * <p> 170 * The returned iterable has an iterator that traverses the elements in {@code a}, 171 * followed by the elements in {@code b} and {@code c}. The source iterators are 172 * not polled until necessary. 173 * </p> 174 * <p> 175 * The returned iterable's iterator supports {@code remove()} when the corresponding 176 * input iterator supports it. 177 * </p> 178 * 179 * @param <E> the element type 180 * @param a the first iterable, may not be null 181 * @param b the second iterable, may not be null 182 * @param c the third iterable, may not be null 183 * @return a new iterable, combining the provided iterables 184 * @throws NullPointerException if either of the provided iterables is null 185 */ 186 @SuppressWarnings("unchecked") 187 public static <E> Iterable<E> chainedIterable(final Iterable<? extends E> a, 188 final Iterable<? extends E> b, 189 final Iterable<? extends E> c) { 190 return chainedIterable(new Iterable[] {a, b, c}); 191 } 192 193 /** 194 * Combines four iterables into a single iterable. 195 * <p> 196 * The returned iterable has an iterator that traverses the elements in {@code a}, 197 * followed by the elements in {@code b}, {@code c} and {@code d}. The source 198 * iterators are not polled until necessary. 199 * </p> 200 * <p> 201 * The returned iterable's iterator supports {@code remove()} when the corresponding 202 * input iterator supports it. 203 * </p> 204 * 205 * @param <E> the element type 206 * @param a the first iterable, may not be null 207 * @param b the second iterable, may not be null 208 * @param c the third iterable, may not be null 209 * @param d the fourth iterable, may not be null 210 * @return a new iterable, combining the provided iterables 211 * @throws NullPointerException if either of the provided iterables is null 212 */ 213 @SuppressWarnings("unchecked") 214 public static <E> Iterable<E> chainedIterable(final Iterable<? extends E> a, 215 final Iterable<? extends E> b, 216 final Iterable<? extends E> c, 217 final Iterable<? extends E> d) { 218 return chainedIterable(new Iterable[] {a, b, c, d}); 219 } 220 221 /** 222 * Fail-fast check for null arguments. 223 * 224 * @param iterables the iterables to check 225 * @throws NullPointerException if the argument or any of its contents is null 226 */ 227 static void checkNotNull(final Iterable<?>... iterables) { 228 Objects.requireNonNull(iterables, "iterables"); 229 for (final Iterable<?> iterable : iterables) { 230 Objects.requireNonNull(iterable, "iterable"); 231 } 232 } 233 234 /** 235 * Combines the two provided iterables into an ordered iterable using the 236 * provided comparator. If the comparator is null, natural ordering will be 237 * used. 238 * <p> 239 * The returned iterable's iterator supports {@code remove()} when the 240 * corresponding input iterator supports it. 241 * </p> 242 * 243 * @param <E> the element type 244 * @param comparator the comparator defining an ordering over the elements, 245 * may be null, in which case natural ordering will be used 246 * @param a the first iterable, may not be null 247 * @param b the second iterable, may not be null 248 * @return a filtered view on the specified iterable 249 * @throws NullPointerException if either of the provided iterables is null 250 */ 251 public static <E> Iterable<E> collatedIterable(final Comparator<? super E> comparator, 252 final Iterable<? extends E> a, 253 final Iterable<? extends E> b) { 254 checkNotNull(a, b); 255 return new FluentIterable<E>() { 256 @Override 257 public Iterator<E> iterator() { 258 return IteratorUtils.collatedIterator(comparator, a.iterator(), b.iterator()); 259 } 260 }; 261 } 262 263 /** 264 * Combines the two provided iterables into an ordered iterable using 265 * natural ordering. 266 * <p> 267 * The returned iterable's iterator supports {@code remove()} when the 268 * corresponding input iterator supports it. 269 * </p> 270 * 271 * @param <E> the element type 272 * @param a the first iterable, must not be null 273 * @param b the second iterable, must not be null 274 * @return a filtered view on the specified iterable 275 * @throws NullPointerException if either of the provided iterables is null 276 */ 277 public static <E> Iterable<E> collatedIterable(final Iterable<? extends E> a, 278 final Iterable<? extends E> b) { 279 checkNotNull(a, b); 280 return new FluentIterable<E>() { 281 @Override 282 public Iterator<E> iterator() { 283 return IteratorUtils.collatedIterator(null, a.iterator(), b.iterator()); 284 } 285 }; 286 } 287 288 /** 289 * Checks if the object is contained in the given iterable. Object equality 290 * is tested with an {@code equator} unlike {@link #contains(Iterable, Object)} 291 * which uses {@link Object#equals(Object)}. 292 * <p> 293 * A {@code null} or empty iterable returns false. 294 * A {@code null} object will not be passed to the equator, instead a 295 * {@link org.apache.commons.collections4.functors.NullPredicate NullPredicate} 296 * will be used. 297 * </p> 298 * 299 * @param <E> the type of object the {@link Iterable} contains 300 * @param iterable the iterable to check, may be null 301 * @param object the object to check 302 * @param equator the equator to use to check, may not be null 303 * @return true if the object is contained in the iterable, false otherwise 304 * @throws NullPointerException if equator is null 305 */ 306 public static <E> boolean contains(final Iterable<? extends E> iterable, final E object, 307 final Equator<? super E> equator) { 308 Objects.requireNonNull(equator, "equator"); 309 return matchesAny(iterable, EqualPredicate.equalPredicate(object, equator)); 310 } 311 312 /** 313 * Checks if the object is contained in the given iterable. 314 * <p> 315 * A {@code null} or empty iterable returns false. 316 * </p> 317 * 318 * @param <E> the type of object the {@link Iterable} contains 319 * @param iterable the iterable to check, may be null 320 * @param object the object to check 321 * @return true if the object is contained in the iterable, false otherwise 322 */ 323 public static <E> boolean contains(final Iterable<E> iterable, final Object object) { 324 if (iterable instanceof Collection<?>) { 325 return ((Collection<E>) iterable).contains(object); 326 } 327 return IteratorUtils.contains(emptyIteratorIfNull(iterable), object); 328 } 329 330 /** 331 * Counts the number of elements in the input iterable that match the predicate. 332 * <p> 333 * A {@code null} iterable matches no elements. 334 * </p> 335 * 336 * @param <E> the type of object the {@link Iterable} contains 337 * @param input the {@link Iterable} to get the input from, may be null 338 * @param predicate the predicate to use, may not be null 339 * @return the number of matches for the predicate in the collection 340 * @throws NullPointerException if predicate is null 341 */ 342 public static <E> long countMatches(final Iterable<E> input, final Predicate<? super E> predicate) { 343 Objects.requireNonNull(predicate, "predicate"); 344 return size(filteredIterable(emptyIfNull(input), predicate)); 345 } 346 347 /** 348 * Finds and returns the List of duplicate elements in the given collection. 349 * 350 * @param <E> the type of elements in the collection. 351 * @param iterable the list to test, must not be null. 352 * @return the set of duplicate elements, may be empty. 353 * @since 4.5.0-M3 354 */ 355 public static <E> List<E> duplicateList(final Iterable<E> iterable) { 356 return new ArrayList<>(duplicateSequencedSet(iterable)); 357 } 358 359 /** 360 * Finds and returns the sequenced Set of duplicate elements in the given collection. 361 * <p> 362 * Once we are on Java 21 and a new major version, the return type should be SequencedSet. 363 * </p> 364 * 365 * @param <E> the type of elements in the collection. 366 * @param iterable the list to test, must not be null. 367 * @return the set of duplicate elements, may be empty. 368 * @since 4.5.0-M3 369 */ 370 public static <E> Set<E> duplicateSequencedSet(final Iterable<E> iterable) { 371 return duplicateSet(iterable, new LinkedHashSet<>()); 372 } 373 374 /** 375 * Finds and returns the set of duplicate elements in the given collection. 376 * 377 * @param <E> the type of elements in the collection. 378 * @param iterable the list to test, must not be null. 379 * @return the set of duplicate elements, may be empty. 380 * @since 4.5.0-M3 381 */ 382 public static <E> Set<E> duplicateSet(final Iterable<E> iterable) { 383 return duplicateSet(iterable, new HashSet<>()); 384 } 385 386 /** 387 * Worker method for {@link #duplicateSet(Collection)} and friends. 388 * 389 * @param <C> the type of Collection. 390 * @param <E> the type of elements in the Collection. 391 * @param iterable the list to test, must not be null. 392 * @param duplicates the list to test, must not be null. 393 * @return the set of duplicate elements, may be empty. 394 */ 395 static <C extends Collection<E>, E> C duplicateSet(final Iterable<E> iterable, final C duplicates) { 396 final Set<E> set = new HashSet<>(); 397 for (final E e : iterable) { 398 (set.contains(e) ? duplicates : set).add(e); 399 } 400 return duplicates; 401 } 402 403 /** 404 * Returns an immutable empty iterable if the argument is null, 405 * or the argument itself otherwise. 406 * 407 * @param <E> the element type 408 * @param iterable the iterable, may be null 409 * @return an empty iterable if the argument is null 410 */ 411 public static <E> Iterable<E> emptyIfNull(final Iterable<E> iterable) { 412 return iterable == null ? IterableUtils.<E>emptyIterable() : iterable; 413 } 414 415 /** 416 * Gets an empty iterable. 417 * <p> 418 * This iterable does not contain any elements. 419 * </p> 420 * 421 * @param <E> the element type 422 * @return an empty iterable 423 */ 424 @SuppressWarnings("unchecked") // OK, empty collection is compatible with any type 425 public static <E> Iterable<E> emptyIterable() { 426 return EMPTY_ITERABLE; 427 } 428 429 /** 430 * Returns an empty iterator if the argument is {@code null}, 431 * or {@code iterable.iterator()} otherwise. 432 * 433 * @param <E> the element type 434 * @param iterable the iterable, possibly {@code null} 435 * @return an empty iterator if the argument is {@code null} 436 */ 437 private static <E> Iterator<E> emptyIteratorIfNull(final Iterable<E> iterable) { 438 return iterable != null ? iterable.iterator() : IteratorUtils.<E>emptyIterator(); 439 } 440 441 /** 442 * Returns a view of the given iterable that only contains elements matching 443 * the provided predicate. 444 * <p> 445 * The returned iterable's iterator supports {@code remove()} when the 446 * corresponding input iterator supports it. 447 * </p> 448 * 449 * @param <E> the element type 450 * @param iterable the iterable to filter, may not be null 451 * @param predicate the predicate used to filter elements, may not be null 452 * @return a filtered view on the specified iterable 453 * @throws NullPointerException if either iterable or predicate is null 454 */ 455 public static <E> Iterable<E> filteredIterable(final Iterable<E> iterable, 456 final Predicate<? super E> predicate) { 457 Objects.requireNonNull(iterable, "iterable"); 458 Objects.requireNonNull(predicate, "predicate"); 459 return new FluentIterable<E>() { 460 @Override 461 public Iterator<E> iterator() { 462 return IteratorUtils.filteredIterator(emptyIteratorIfNull(iterable), predicate); 463 } 464 }; 465 } 466 467 /** 468 * Finds the first element in the given iterable which matches the given predicate. 469 * <p> 470 * A {@code null} or empty iterator returns null. 471 * </p> 472 * 473 * @param <E> the element type 474 * @param iterable the iterable to search, may be null 475 * @param predicate the predicate to use, must not be null 476 * @return the first element of the iterable which matches the predicate or null if none could be found 477 * @throws NullPointerException if predicate is null 478 */ 479 public static <E> E find(final Iterable<E> iterable, final Predicate<? super E> predicate) { 480 return IteratorUtils.find(emptyIteratorIfNull(iterable), predicate); 481 } 482 483 /** 484 * Shortcut for {@code get(iterator, 0)}. 485 * <p> 486 * Returns the {@code first} value in the {@code iterable}'s {@link Iterator}, throwing 487 * {@code IndexOutOfBoundsException} if there is no such element. 488 * </p> 489 * <p> 490 * If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}. 491 * </p> 492 * 493 * @param <T> the type of object in the {@link Iterable}. 494 * @param iterable the {@link Iterable} to get a value from, may be null 495 * @return the first object 496 * @throws IndexOutOfBoundsException if the request is invalid 497 * @since 4.2 498 */ 499 public static <T> T first(final Iterable<T> iterable) { 500 return get(iterable, 0); 501 } 502 503 /** 504 * Applies the closure to each element of the provided iterable. 505 * 506 * @param <E> the element type 507 * @param iterable the iterator to use, may be null 508 * @param closure the closure to apply to each element, may not be null 509 * @throws NullPointerException if closure is null 510 */ 511 public static <E> void forEach(final Iterable<E> iterable, final Closure<? super E> closure) { 512 IteratorUtils.forEach(emptyIteratorIfNull(iterable), closure); 513 } 514 515 /** 516 * Executes the given closure on each but the last element in the iterable. 517 * <p> 518 * If the input iterable is null no change is made. 519 * </p> 520 * 521 * @param <E> the type of object the {@link Iterable} contains 522 * @param iterable the iterable to get the input from, may be null 523 * @param closure the closure to perform, may not be null 524 * @return the last element in the iterable, or null if iterable is null or empty 525 */ 526 public static <E> E forEachButLast(final Iterable<E> iterable, final Closure<? super E> closure) { 527 return IteratorUtils.forEachButLast(emptyIteratorIfNull(iterable), closure); 528 } 529 530 /** 531 * Returns the number of occurrences of the provided object in the iterable. 532 * 533 * @param <E> the element type that the {@link Iterable} may contain 534 * @param <T> the element type of the object to find 535 * @param iterable the {@link Iterable} to search 536 * @param obj the object to find the cardinality of 537 * @return the number of occurrences of obj in iterable 538 */ 539 public static <E, T extends E> int frequency(final Iterable<E> iterable, final T obj) { 540 if (iterable instanceof Set<?>) { 541 return ((Set<E>) iterable).contains(obj) ? 1 : 0; 542 } 543 if (iterable instanceof Bag<?>) { 544 return ((Bag<E>) iterable).getCount(obj); 545 } 546 return size(filteredIterable(emptyIfNull(iterable), EqualPredicate.<E>equalPredicate(obj))); 547 } 548 549 /** 550 * Returns the {@code index}-th value in the {@code iterable}'s {@link Iterator}, throwing 551 * {@code IndexOutOfBoundsException} if there is no such element. 552 * <p> 553 * If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}. 554 * </p> 555 * 556 * @param <T> the type of object in the {@link Iterable}. 557 * @param iterable the {@link Iterable} to get a value from, may be null 558 * @param index the index to get 559 * @return the object at the specified index 560 * @throws IndexOutOfBoundsException if the index is invalid 561 */ 562 public static <T> T get(final Iterable<T> iterable, final int index) { 563 CollectionUtils.checkIndexBounds(index); 564 if (iterable instanceof List<?>) { 565 return ((List<T>) iterable).get(index); 566 } 567 return IteratorUtils.get(emptyIteratorIfNull(iterable), index); 568 } 569 570 /** 571 * Returns the index of the first element in the specified iterable that 572 * matches the given predicate. 573 * <p> 574 * A {@code null} or empty iterable returns -1. 575 * </p> 576 * 577 * @param <E> the element type 578 * @param iterable the iterable to search, may be null 579 * @param predicate the predicate to use, must not be null 580 * @return the index of the first element which matches the predicate or -1 if none matches 581 * @throws NullPointerException if predicate is null 582 */ 583 public static <E> int indexOf(final Iterable<E> iterable, final Predicate<? super E> predicate) { 584 return IteratorUtils.indexOf(emptyIteratorIfNull(iterable), predicate); 585 } 586 587 /** 588 * Answers true if the provided iterable is empty. 589 * <p> 590 * A {@code null} iterable returns true. 591 * </p> 592 * 593 * @param iterable the {@link Iterable to use}, may be null 594 * @return true if the iterable is null or empty, false otherwise 595 */ 596 public static boolean isEmpty(final Iterable<?> iterable) { 597 if (iterable instanceof Collection<?>) { 598 return ((Collection<?>) iterable).isEmpty(); 599 } 600 return IteratorUtils.isEmpty(emptyIteratorIfNull(iterable)); 601 } 602 603 /** 604 * Returns a view of the given iterable which will cycle infinitely over 605 * its elements. 606 * <p> 607 * The returned iterable's iterator supports {@code remove()} if 608 * {@code iterable.iterator()} does. After {@code remove()} is called, subsequent 609 * cycles omit the removed element, which is no longer in {@code iterable}. The 610 * iterator's {@code hasNext()} method returns {@code true} until {@code iterable} 611 * is empty. 612 * </p> 613 * 614 * @param <E> the element type 615 * @param iterable the iterable to loop, may not be null 616 * @return a view of the iterable, providing an infinite loop over its elements 617 * @throws NullPointerException if iterable is null 618 */ 619 public static <E> Iterable<E> loopingIterable(final Iterable<E> iterable) { 620 Objects.requireNonNull(iterable, "iterable"); 621 return new FluentIterable<E>() { 622 @Override 623 public Iterator<E> iterator() { 624 return new LazyIteratorChain<E>() { 625 @Override 626 protected Iterator<? extends E> nextIterator(final int count) { 627 if (IterableUtils.isEmpty(iterable)) { 628 return null; 629 } 630 return iterable.iterator(); 631 } 632 }; 633 } 634 }; 635 } 636 637 /** 638 * Answers true if a predicate is true for every element of an iterable. 639 * <p> 640 * A {@code null} or empty iterable returns true. 641 * </p> 642 * 643 * @param <E> the type of object the {@link Iterable} contains 644 * @param iterable the {@link Iterable} to use, may be null 645 * @param predicate the predicate to use, may not be null 646 * @return true if every element of the collection matches the predicate or if the 647 * collection is empty, false otherwise 648 * @throws NullPointerException if predicate is null 649 */ 650 public static <E> boolean matchesAll(final Iterable<E> iterable, final Predicate<? super E> predicate) { 651 return IteratorUtils.matchesAll(emptyIteratorIfNull(iterable), predicate); 652 } 653 654 /** 655 * Answers true if a predicate is true for any element of the iterable. 656 * <p> 657 * A {@code null} or empty iterable returns false. 658 * </p> 659 * 660 * @param <E> the type of object the {@link Iterable} contains 661 * @param iterable the {@link Iterable} to use, may be null 662 * @param predicate the predicate to use, may not be null 663 * @return true if any element of the collection matches the predicate, false otherwise 664 * @throws NullPointerException if predicate is null 665 */ 666 public static <E> boolean matchesAny(final Iterable<E> iterable, final Predicate<? super E> predicate) { 667 return IteratorUtils.matchesAny(emptyIteratorIfNull(iterable), predicate); 668 } 669 670 /** 671 * Partitions all elements from iterable into separate output collections, 672 * based on the evaluation of the given predicates. 673 * <p> 674 * For each predicate, the returned list will contain a collection holding 675 * all elements of the input iterable matching the predicate. The last collection 676 * contained in the list will hold all elements which didn't match any predicate: 677 * </p> 678 * <pre> 679 * [C1, C2, R] = partition(I, P1, P2) with 680 * I = input 681 * P1 = first predicate 682 * P2 = second predicate 683 * C1 = collection of elements matching P1 684 * C2 = collection of elements matching P2 685 * R = collection of elements rejected by all predicates 686 * </pre> 687 * <p> 688 * <strong>Note</strong>: elements are only added to the output collection of the first matching 689 * predicate, determined by the order of arguments. 690 * </p> 691 * <p> 692 * If the input iterable is {@code null}, the same is returned as for an 693 * empty iterable. 694 * If no predicates have been provided, all elements of the input collection 695 * will be added to the rejected collection. 696 * </p> 697 * <p> 698 * Example: for an input list [1, 2, 3, 4, 5] calling partition with predicates [x < 3] 699 * and [x < 5] will result in the following output: [[1, 2], [3, 4], [5]]. 700 * </p> 701 * 702 * @param <O> the type of object the {@link Iterable} contains 703 * @param <R> the type of the output {@link Collection} 704 * @param iterable the collection to get the input from, may be null 705 * @param partitionFactory the factory used to create the output collections 706 * @param predicates the predicates to use, may not be null 707 * @return a list containing the output collections 708 * @throws NullPointerException if any predicate is null 709 */ 710 public static <O, R extends Collection<O>> List<R> partition(final Iterable<? extends O> iterable, 711 final Factory<R> partitionFactory, final Predicate<? super O>... predicates) { 712 713 if (iterable == null) { 714 final Iterable<O> empty = emptyIterable(); 715 return partition(empty, partitionFactory, predicates); 716 } 717 718 Objects.requireNonNull(predicates, "predicates"); 719 720 for (final Predicate<?> predicate : predicates) { 721 Objects.requireNonNull(predicate, "predicate"); 722 } 723 724 if (predicates.length < 1) { 725 // return the entire input collection as a single partition 726 final R singlePartition = partitionFactory.get(); 727 CollectionUtils.addAll(singlePartition, iterable); 728 return Collections.singletonList(singlePartition); 729 } 730 731 // create the empty partitions 732 final int numberOfPredicates = predicates.length; 733 final int numberOfPartitions = numberOfPredicates + 1; 734 final List<R> partitions = new ArrayList<>(numberOfPartitions); 735 for (int i = 0; i < numberOfPartitions; ++i) { 736 partitions.add(partitionFactory.get()); 737 } 738 739 // for each element in inputCollection: 740 // find the first predicate that evaluates to true. 741 // if there is a predicate, add the element to the corresponding partition. 742 // if there is no predicate, add it to the last, catch-all partition. 743 for (final O element : iterable) { 744 boolean elementAssigned = false; 745 for (int i = 0; i < numberOfPredicates; ++i) { 746 if (predicates[i].test(element)) { 747 partitions.get(i).add(element); 748 elementAssigned = true; 749 break; 750 } 751 } 752 753 if (!elementAssigned) { 754 // no predicates evaluated to true 755 // add element to last partition 756 partitions.get(numberOfPredicates).add(element); 757 } 758 } 759 760 return partitions; 761 } 762 763 /** 764 * Partitions all elements from iterable into separate output collections, 765 * based on the evaluation of the given predicate. 766 * <p> 767 * For each predicate, the result will contain a list holding all elements of the 768 * input iterable matching the predicate. The last list will hold all elements 769 * which didn't match any predicate: 770 * </p> 771 * <pre> 772 * [C1, R] = partition(I, P1) with 773 * I = input 774 * P1 = first predicate 775 * C1 = collection of elements matching P1 776 * R = collection of elements rejected by all predicates 777 * </pre> 778 * <p> 779 * If the input iterable is {@code null}, the same is returned as for an 780 * empty iterable. 781 * </p> 782 * <p> 783 * Example: for an input list [1, 2, 3, 4, 5] calling partition with a predicate [x < 3] 784 * will result in the following output: [[1, 2], [3, 4, 5]]. 785 * </p> 786 * 787 * @param <O> the type of object the {@link Iterable} contains 788 * @param iterable the iterable to partition, may be null 789 * @param predicate the predicate to use, may not be null 790 * @return a list containing the output collections 791 * @throws NullPointerException if predicate is null 792 */ 793 public static <O> List<List<O>> partition(final Iterable<? extends O> iterable, 794 final Predicate<? super O> predicate) { 795 Objects.requireNonNull(predicate, "predicate"); 796 @SuppressWarnings({ "unchecked", "rawtypes" }) // safe 797 final Factory<List<O>> factory = FactoryUtils.instantiateFactory((Class) ArrayList.class); 798 @SuppressWarnings("unchecked") // safe 799 final Predicate<? super O>[] predicates = new Predicate[] { predicate }; 800 return partition(iterable, factory, predicates); 801 } 802 803 /** 804 * Partitions all elements from iterable into separate output collections, 805 * based on the evaluation of the given predicates. 806 * <p> 807 * For each predicate, the result will contain a list holding all elements of the 808 * input iterable matching the predicate. The last list will hold all elements 809 * which didn't match any predicate: 810 * </p> 811 * <pre> 812 * [C1, C2, R] = partition(I, P1, P2) with 813 * I = input 814 * P1 = first predicate 815 * P2 = second predicate 816 * C1 = collection of elements matching P1 817 * C2 = collection of elements matching P2 818 * R = collection of elements rejected by all predicates 819 * </pre> 820 * <p> 821 * <strong>Note</strong>: elements are only added to the output collection of the first matching 822 * predicate, determined by the order of arguments. 823 * </p> 824 * <p> 825 * If the input iterable is {@code null}, the same is returned as for an 826 * empty iterable. 827 * </p> 828 * <p> 829 * Example: for an input list [1, 2, 3, 4, 5] calling partition with predicates [x < 3] 830 * and [x < 5] will result in the following output: [[1, 2], [3, 4], [5]]. 831 * </p> 832 * 833 * @param <O> the type of object the {@link Iterable} contains 834 * @param iterable the collection to get the input from, may be null 835 * @param predicates the predicates to use, may not be null 836 * @return a list containing the output collections 837 * @throws NullPointerException if any predicate is null 838 */ 839 public static <O> List<List<O>> partition(final Iterable<? extends O> iterable, 840 final Predicate<? super O>... predicates) { 841 842 @SuppressWarnings({ "unchecked", "rawtypes" }) // safe 843 final Factory<List<O>> factory = FactoryUtils.instantiateFactory((Class) ArrayList.class); 844 return partition(iterable, factory, predicates); 845 } 846 847 /** 848 * Returns a reversed view of the given iterable. 849 * <p> 850 * In case the provided iterable is a {@link List} instance, a 851 * {@link ReverseListIterator} will be used to reverse the traversal 852 * order, otherwise an intermediate {@link List} needs to be created. 853 * </p> 854 * <p> 855 * The returned iterable's iterator supports {@code remove()} if the 856 * provided iterable is a {@link List} instance. 857 * </p> 858 * 859 * @param <E> the element type 860 * @param iterable the iterable to use, may not be null 861 * @return a reversed view of the specified iterable 862 * @throws NullPointerException if iterable is null 863 * @see ReverseListIterator 864 */ 865 public static <E> Iterable<E> reversedIterable(final Iterable<E> iterable) { 866 Objects.requireNonNull(iterable, "iterable"); 867 return new FluentIterable<E>() { 868 @Override 869 public Iterator<E> iterator() { 870 final List<E> list = iterable instanceof List<?> ? 871 (List<E>) iterable : 872 IteratorUtils.toList(iterable.iterator()); 873 return new ReverseListIterator<>(list); 874 } 875 }; 876 } 877 878 /** 879 * Returns the number of elements contained in the given iterator. 880 * <p> 881 * A {@code null} or empty iterator returns {@code 0}. 882 * </p> 883 * 884 * @param iterable the iterable to check, may be null 885 * @return the number of elements contained in the iterable 886 */ 887 public static int size(final Iterable<?> iterable) { 888 if (iterable == null) { 889 return 0; 890 } 891 if (iterable instanceof Collection<?>) { 892 return ((Collection<?>) iterable).size(); 893 } 894 return IteratorUtils.size(emptyIteratorIfNull(iterable)); 895 } 896 897 /** 898 * Returns a view of the given iterable that skips the first N elements. 899 * <p> 900 * The returned iterable's iterator supports {@code remove()} when the corresponding 901 * input iterator supports it. 902 * </p> 903 * 904 * @param <E> the element type 905 * @param iterable the iterable to use, may not be null 906 * @param elementsToSkip the number of elements to skip from the start, must not be negative 907 * @return a view of the specified iterable, skipping the first N elements 908 * @throws IllegalArgumentException if elementsToSkip is negative 909 * @throws NullPointerException if iterable is null 910 */ 911 public static <E> Iterable<E> skippingIterable(final Iterable<E> iterable, final long elementsToSkip) { 912 Objects.requireNonNull(iterable, "iterable"); 913 if (elementsToSkip < 0) { 914 throw new IllegalArgumentException("ElementsToSkip parameter must not be negative."); 915 } 916 917 return new FluentIterable<E>() { 918 @Override 919 public Iterator<E> iterator() { 920 return IteratorUtils.skippingIterator(iterable.iterator(), elementsToSkip); 921 } 922 }; 923 } 924 925 /** 926 * Gets a new list with the contents of the provided iterable. 927 * 928 * @param <E> the element type 929 * @param iterable the iterable to use, may be null 930 * @return a list of the iterator contents 931 */ 932 public static <E> List<E> toList(final Iterable<E> iterable) { 933 return IteratorUtils.toList(emptyIteratorIfNull(iterable)); 934 } 935 936 /** 937 * Returns a string representation of the elements of the specified iterable. 938 * <p> 939 * The string representation consists of a list of the iterable's elements, 940 * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated 941 * by the characters {@code ", "} (a comma followed by a space). Elements are 942 * converted to strings as by {@code String.valueOf(Object)}. 943 * </p> 944 * 945 * @param <E> the element type 946 * @param iterable the iterable to convert to a string, may be null 947 * @return a string representation of {@code iterable} 948 */ 949 public static <E> String toString(final Iterable<E> iterable) { 950 return IteratorUtils.toString(emptyIteratorIfNull(iterable)); 951 } 952 953 /** 954 * Returns a string representation of the elements of the specified iterable. 955 * <p> 956 * The string representation consists of a list of the iterable's elements, 957 * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated 958 * by the characters {@code ", "} (a comma followed by a space). Elements are 959 * converted to strings as by using the provided {@code transformer}. 960 * </p> 961 * 962 * @param <E> the element type 963 * @param iterable the iterable to convert to a string, may be null 964 * @param transformer the transformer used to get a string representation of an element 965 * @return a string representation of {@code iterable} 966 * @throws NullPointerException if {@code transformer} is null 967 */ 968 public static <E> String toString(final Iterable<E> iterable, 969 final Transformer<? super E, String> transformer) { 970 Objects.requireNonNull(transformer, "transformer"); 971 return IteratorUtils.toString(emptyIteratorIfNull(iterable), transformer); 972 } 973 974 /** 975 * Returns a string representation of the elements of the specified iterable. 976 * <p> 977 * The string representation consists of a list of the iterable's elements, 978 * enclosed by the provided {@code prefix} and {@code suffix}. Adjacent elements 979 * are separated by the provided {@code delimiter}. Elements are converted to 980 * strings as by using the provided {@code transformer}. 981 * </p> 982 * 983 * @param <E> the element type 984 * @param iterable the iterable to convert to a string, may be null 985 * @param transformer the transformer used to get a string representation of an element 986 * @param delimiter the string to delimit elements 987 * @param prefix the prefix, prepended to the string representation 988 * @param suffix the suffix, appended to the string representation 989 * @return a string representation of {@code iterable} 990 * @throws NullPointerException if either transformer, delimiter, prefix or suffix is null 991 */ 992 public static <E> String toString(final Iterable<E> iterable, 993 final Transformer<? super E, String> transformer, 994 final String delimiter, 995 final String prefix, 996 final String suffix) { 997 return IteratorUtils.toString(emptyIteratorIfNull(iterable), 998 transformer, delimiter, prefix, suffix); 999 } 1000 1001 /** 1002 * Returns a transformed view of the given iterable where all of its elements 1003 * have been transformed by the provided transformer. 1004 * <p> 1005 * The returned iterable's iterator supports {@code remove()} when the corresponding 1006 * input iterator supports it. 1007 * </p> 1008 * 1009 * @param <I> the input element type 1010 * @param <O> the output element type 1011 * @param iterable the iterable to transform, may not be null 1012 * @param transformer the transformer, must not be null 1013 * @return a transformed view of the specified iterable 1014 * @throws NullPointerException if either iterable or transformer is null 1015 */ 1016 public static <I, O> Iterable<O> transformedIterable(final Iterable<I> iterable, 1017 final Transformer<? super I, ? extends O> transformer) { 1018 Objects.requireNonNull(iterable, "iterable"); 1019 Objects.requireNonNull(transformer, "transformer"); 1020 return new FluentIterable<O>() { 1021 @Override 1022 public Iterator<O> iterator() { 1023 return IteratorUtils.transformedIterator(iterable.iterator(), transformer); 1024 } 1025 }; 1026 } 1027 1028 /** 1029 * Returns a unique view of the given iterable. 1030 * <p> 1031 * The returned iterable's iterator supports {@code remove()} when the 1032 * corresponding input iterator supports it. Calling {@code remove()} 1033 * will only remove a single element from the underlying iterator. 1034 * </p> 1035 * 1036 * @param <E> the element type 1037 * @param iterable the iterable to use, may not be null 1038 * @return a unique view of the specified iterable 1039 * @throws NullPointerException if iterable is null 1040 */ 1041 public static <E> Iterable<E> uniqueIterable(final Iterable<E> iterable) { 1042 Objects.requireNonNull(iterable, "iterable"); 1043 return new FluentIterable<E>() { 1044 @Override 1045 public Iterator<E> iterator() { 1046 return new UniqueFilterIterator<>(iterable.iterator()); 1047 } 1048 }; 1049 } 1050 1051 /** 1052 * Returns an unmodifiable view of the given iterable. 1053 * <p> 1054 * The returned iterable's iterator does not support {@code remove()}. 1055 * </p> 1056 * 1057 * @param <E> the element type 1058 * @param iterable the iterable to use, may not be null 1059 * @return an unmodifiable view of the specified iterable 1060 * @throws NullPointerException if iterable is null 1061 */ 1062 public static <E> Iterable<E> unmodifiableIterable(final Iterable<E> iterable) { 1063 Objects.requireNonNull(iterable, "iterable"); 1064 if (iterable instanceof UnmodifiableIterable<?>) { 1065 return iterable; 1066 } 1067 return new UnmodifiableIterable<>(iterable); 1068 } 1069 1070 /** 1071 * Interleaves two iterables into a single iterable. 1072 * <p> 1073 * The returned iterable has an iterator that traverses the elements in {@code a} 1074 * and {@code b} in alternating order. The source iterators are not polled until 1075 * necessary. 1076 * </p> 1077 * <p> 1078 * The returned iterable's iterator supports {@code remove()} when the corresponding 1079 * input iterator supports it. 1080 * </p> 1081 * 1082 * @param <E> the element type 1083 * @param a the first iterable, may not be null 1084 * @param b the second iterable, may not be null 1085 * @return a new iterable, interleaving the provided iterables 1086 * @throws NullPointerException if either a or b is null 1087 */ 1088 public static <E> Iterable<E> zippingIterable(final Iterable<? extends E> a, 1089 final Iterable<? extends E> b) { 1090 Objects.requireNonNull(a, "iterable"); 1091 Objects.requireNonNull(b, "iterable"); 1092 return new FluentIterable<E>() { 1093 @Override 1094 public Iterator<E> iterator() { 1095 return IteratorUtils.zippingIterator(a.iterator(), b.iterator()); 1096 } 1097 }; 1098 } 1099 1100 /** 1101 * Interleaves two iterables into a single iterable. 1102 * <p> 1103 * The returned iterable has an iterator that traverses the elements in {@code a} and {@code b} in alternating order. The source iterators are not polled 1104 * until necessary. 1105 * </p> 1106 * <p> 1107 * The returned iterable's iterator supports {@code remove()} when the corresponding input iterator supports it. 1108 * </p> 1109 * 1110 * @param <E> the element type 1111 * @param first the first iterable, may not be null 1112 * @param others the array of iterables to interleave, may not be null 1113 * @return a new iterable, interleaving the provided iterables 1114 * @throws NullPointerException if either of the provided iterables is null 1115 */ 1116 public static <E> Iterable<E> zippingIterable(final Iterable<? extends E> first, final Iterable<? extends E>... others) { 1117 Objects.requireNonNull(first, "iterable"); 1118 checkNotNull(others); 1119 return new FluentIterable<E>() { 1120 @Override 1121 public Iterator<E> iterator() { 1122 @SuppressWarnings("unchecked") // safe 1123 final Iterator<? extends E>[] iterators = new Iterator[others.length + 1]; 1124 iterators[0] = first.iterator(); 1125 for (int i = 0; i < others.length; i++) { 1126 iterators[i + 1] = others[i].iterator(); 1127 } 1128 return IteratorUtils.zippingIterator(iterators); 1129 } 1130 }; 1131 } 1132 1133 /** 1134 * Make private in 5.0. 1135 * 1136 * @deprecated TODO Make private in 5.0. 1137 */ 1138 @Deprecated 1139 public IterableUtils() { 1140 // empty 1141 } 1142 }