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