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.lang.reflect.Array; 020import java.lang.reflect.Method; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Comparator; 024import java.util.Dictionary; 025import java.util.Enumeration; 026import java.util.Iterator; 027import java.util.List; 028import java.util.ListIterator; 029import java.util.Map; 030import java.util.Objects; 031 032import org.apache.commons.collections4.functors.EqualPredicate; 033import org.apache.commons.collections4.iterators.ArrayIterator; 034import org.apache.commons.collections4.iterators.ArrayListIterator; 035import org.apache.commons.collections4.iterators.BoundedIterator; 036import org.apache.commons.collections4.iterators.CollatingIterator; 037import org.apache.commons.collections4.iterators.EmptyIterator; 038import org.apache.commons.collections4.iterators.EmptyListIterator; 039import org.apache.commons.collections4.iterators.EmptyMapIterator; 040import org.apache.commons.collections4.iterators.EmptyOrderedIterator; 041import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator; 042import org.apache.commons.collections4.iterators.EnumerationIterator; 043import org.apache.commons.collections4.iterators.FilterIterator; 044import org.apache.commons.collections4.iterators.FilterListIterator; 045import org.apache.commons.collections4.iterators.IteratorChain; 046import org.apache.commons.collections4.iterators.IteratorEnumeration; 047import org.apache.commons.collections4.iterators.IteratorIterable; 048import org.apache.commons.collections4.iterators.ListIteratorWrapper; 049import org.apache.commons.collections4.iterators.LoopingIterator; 050import org.apache.commons.collections4.iterators.LoopingListIterator; 051import org.apache.commons.collections4.iterators.NodeListIterator; 052import org.apache.commons.collections4.iterators.ObjectArrayIterator; 053import org.apache.commons.collections4.iterators.ObjectArrayListIterator; 054import org.apache.commons.collections4.iterators.ObjectGraphIterator; 055import org.apache.commons.collections4.iterators.PeekingIterator; 056import org.apache.commons.collections4.iterators.PushbackIterator; 057import org.apache.commons.collections4.iterators.SingletonIterator; 058import org.apache.commons.collections4.iterators.SingletonListIterator; 059import org.apache.commons.collections4.iterators.SkippingIterator; 060import org.apache.commons.collections4.iterators.TransformIterator; 061import org.apache.commons.collections4.iterators.UnmodifiableIterator; 062import org.apache.commons.collections4.iterators.UnmodifiableListIterator; 063import org.apache.commons.collections4.iterators.UnmodifiableMapIterator; 064import org.apache.commons.collections4.iterators.ZippingIterator; 065import org.w3c.dom.Node; 066import org.w3c.dom.NodeList; 067 068/** 069 * Provides static utility methods and decorators for {@link Iterator} 070 * instances. The implementations are provided in the iterators subpackage. 071 * 072 * @since 2.1 073 */ 074public class IteratorUtils { 075 // validation is done in this class in certain cases because the 076 // public classes allow invalid states 077 078 /** 079 * An iterator over no elements. 080 */ 081 @SuppressWarnings("rawtypes") 082 public static final ResettableIterator EMPTY_ITERATOR = EmptyIterator.RESETTABLE_INSTANCE; 083 084 /** 085 * A list iterator over no elements. 086 */ 087 @SuppressWarnings("rawtypes") 088 public static final ResettableListIterator EMPTY_LIST_ITERATOR = EmptyListIterator.RESETTABLE_INSTANCE; 089 090 /** 091 * An ordered iterator over no elements. 092 */ 093 @SuppressWarnings("rawtypes") 094 public static final OrderedIterator EMPTY_ORDERED_ITERATOR = EmptyOrderedIterator.INSTANCE; 095 096 /** 097 * A map iterator over no elements. 098 */ 099 @SuppressWarnings("rawtypes") 100 public static final MapIterator EMPTY_MAP_ITERATOR = EmptyMapIterator.INSTANCE; 101 102 /** 103 * An ordered map iterator over no elements. 104 */ 105 @SuppressWarnings("rawtypes") 106 public static final OrderedMapIterator EMPTY_ORDERED_MAP_ITERATOR = EmptyOrderedMapIterator.INSTANCE; 107 /** 108 * Default delimiter used to delimit elements while converting an Iterator 109 * to its String representation. 110 */ 111 private static final String DEFAULT_TOSTRING_DELIMITER = ", "; 112 113 // Arrays 114 /** 115 * Gets an iterator over an object array. 116 * 117 * @param <E> the element type 118 * @param array the array over which to iterate 119 * @return an iterator over the array 120 * @throws NullPointerException if array is null 121 */ 122 public static <E> ResettableIterator<E> arrayIterator(final E... array) { 123 return new ObjectArrayIterator<>(array); 124 } 125 126 /** 127 * Gets an iterator over the end part of an object array. 128 * 129 * @param <E> the element type 130 * @param array the array over which to iterate 131 * @param start the index to start iterating at 132 * @return an iterator over part of the array 133 * @throws IndexOutOfBoundsException if start is less than zero or greater 134 * than the length of the array 135 * @throws NullPointerException if array is null 136 */ 137 public static <E> ResettableIterator<E> arrayIterator(final E[] array, final int start) { 138 return new ObjectArrayIterator<>(array, start); 139 } 140 141 /** 142 * Gets an iterator over part of an object array. 143 * 144 * @param <E> the element type 145 * @param array the array over which to iterate 146 * @param start the index to start iterating at 147 * @param end the index to finish iterating at 148 * @return an iterator over part of the array 149 * @throws IndexOutOfBoundsException if array bounds are invalid 150 * @throws IllegalArgumentException if end is before start 151 * @throws NullPointerException if array is null 152 */ 153 public static <E> ResettableIterator<E> arrayIterator(final E[] array, final int start, final int end) { 154 return new ObjectArrayIterator<>(array, start, end); 155 } 156 157 /** 158 * Gets an iterator over an object or primitive array. 159 * <p> 160 * This method will handle primitive arrays as well as object arrays. 161 * The primitives will be wrapped in the appropriate wrapper class. 162 * 163 * @param <E> the element type 164 * @param array the array over which to iterate 165 * @return an iterator over the array 166 * @throws IllegalArgumentException if the array is not an array 167 * @throws NullPointerException if array is null 168 */ 169 public static <E> ResettableIterator<E> arrayIterator(final Object array) { 170 return new ArrayIterator<>(array); 171 } 172 173 /** 174 * Gets an iterator over the end part of an object or primitive array. 175 * <p> 176 * This method will handle primitive arrays as well as object arrays. 177 * The primitives will be wrapped in the appropriate wrapper class. 178 * 179 * @param <E> the element type 180 * @param array the array over which to iterate 181 * @param start the index to start iterating at 182 * @return an iterator over part of the array 183 * @throws IllegalArgumentException if the array is not an array 184 * @throws IndexOutOfBoundsException if start is less than zero or greater 185 * than the length of the array 186 * @throws NullPointerException if array is null 187 */ 188 public static <E> ResettableIterator<E> arrayIterator(final Object array, final int start) { 189 return new ArrayIterator<>(array, start); 190 } 191 192 /** 193 * Gets an iterator over part of an object or primitive array. 194 * <p> 195 * This method will handle primitive arrays as well as object arrays. 196 * The primitives will be wrapped in the appropriate wrapper class. 197 * 198 * @param <E> the element type 199 * @param array the array over which to iterate 200 * @param start the index to start iterating at 201 * @param end the index to finish iterating at 202 * @return an iterator over part of the array 203 * @throws IllegalArgumentException if the array is not an array or end is before start 204 * @throws IndexOutOfBoundsException if array bounds are invalid 205 * @throws NullPointerException if array is null 206 */ 207 public static <E> ResettableIterator<E> arrayIterator(final Object array, final int start, final int end) { 208 return new ArrayIterator<>(array, start, end); 209 } 210 211 /** 212 * Gets a list iterator over an object array. 213 * 214 * @param <E> the element type 215 * @param array the array over which to iterate 216 * @return a list iterator over the array 217 * @throws NullPointerException if array is null 218 */ 219 public static <E> ResettableListIterator<E> arrayListIterator(final E... array) { 220 return new ObjectArrayListIterator<>(array); 221 } 222 223 /** 224 * Gets a list iterator over the end part of an object array. 225 * 226 * @param <E> the element type 227 * @param array the array over which to iterate 228 * @param start the index to start iterating at 229 * @return a list iterator over part of the array 230 * @throws IndexOutOfBoundsException if start is less than zero 231 * @throws NullPointerException if array is null 232 */ 233 public static <E> ResettableListIterator<E> arrayListIterator(final E[] array, final int start) { 234 return new ObjectArrayListIterator<>(array, start); 235 } 236 237 /** 238 * Gets a list iterator over part of an object array. 239 * 240 * @param <E> the element type 241 * @param array the array over which to iterate 242 * @param start the index to start iterating at 243 * @param end the index to finish iterating at 244 * @return a list iterator over part of the array 245 * @throws IndexOutOfBoundsException if array bounds are invalid 246 * @throws IllegalArgumentException if end is before start 247 * @throws NullPointerException if array is null 248 */ 249 public static <E> ResettableListIterator<E> arrayListIterator(final E[] array, final int start, final int end) { 250 return new ObjectArrayListIterator<>(array, start, end); 251 } 252 253 /** 254 * Gets a list iterator over an object or primitive array. 255 * <p> 256 * This method will handle primitive arrays as well as object arrays. 257 * The primitives will be wrapped in the appropriate wrapper class. 258 * 259 * @param <E> the element type 260 * @param array the array over which to iterate 261 * @return a list iterator over the array 262 * @throws IllegalArgumentException if the array is not an array 263 * @throws NullPointerException if array is null 264 */ 265 public static <E> ResettableListIterator<E> arrayListIterator(final Object array) { 266 return new ArrayListIterator<>(array); 267 } 268 269 /** 270 * Gets a list iterator over the end part of an object or primitive array. 271 * <p> 272 * This method will handle primitive arrays as well as object arrays. 273 * The primitives will be wrapped in the appropriate wrapper class. 274 * 275 * @param <E> the element type 276 * @param array the array over which to iterate 277 * @param start the index to start iterating at 278 * @return a list iterator over part of the array 279 * @throws IllegalArgumentException if the array is not an array 280 * @throws IndexOutOfBoundsException if start is less than zero 281 * @throws NullPointerException if array is null 282 */ 283 public static <E> ResettableListIterator<E> arrayListIterator(final Object array, final int start) { 284 return new ArrayListIterator<>(array, start); 285 } 286 287 /** 288 * Gets a list iterator over part of an object or primitive array. 289 * <p> 290 * This method will handle primitive arrays as well as object arrays. 291 * The primitives will be wrapped in the appropriate wrapper class. 292 * 293 * @param <E> the element type 294 * @param array the array over which to iterate 295 * @param start the index to start iterating at 296 * @param end the index to finish iterating at 297 * @return a list iterator over part of the array 298 * @throws IllegalArgumentException if the array is not an array or end is before start 299 * @throws IndexOutOfBoundsException if array bounds are invalid 300 * @throws NullPointerException if array is null 301 */ 302 public static <E> ResettableListIterator<E> arrayListIterator(final Object array, final int start, final int end) { 303 return new ArrayListIterator<>(array, start, end); 304 } 305 306 /** 307 * Gets an enumeration that wraps an iterator. 308 * 309 * @param <E> the element type 310 * @param iterator the iterator to use, may not be null 311 * @return a new enumeration 312 * @throws NullPointerException if iterator is null 313 */ 314 public static <E> Enumeration<E> asEnumeration(final Iterator<? extends E> iterator) { 315 return new IteratorEnumeration<>(Objects.requireNonNull(iterator, "iterator")); 316 } 317 318 /** 319 * Gets an {@link Iterable} that wraps an iterator. The returned {@link Iterable} can be 320 * used for a single iteration. 321 * 322 * @param <E> the element type 323 * @param iterator the iterator to use, may not be null 324 * @return a new, single use {@link Iterable} 325 * @throws NullPointerException if iterator is null 326 */ 327 public static <E> Iterable<E> asIterable(final Iterator<? extends E> iterator) { 328 Objects.requireNonNull(iterator, "iterator"); 329 return new IteratorIterable<>(iterator, false); 330 } 331 332 // Views 333 /** 334 * Gets an iterator that provides an iterator view of the given enumeration. 335 * 336 * @param <E> the element type 337 * @param enumeration the enumeration to use, may not be null 338 * @return a new iterator 339 * @throws NullPointerException if enumeration is null 340 */ 341 public static <E> Iterator<E> asIterator(final Enumeration<? extends E> enumeration) { 342 return new EnumerationIterator<>(Objects.requireNonNull(enumeration, "enumeration")); 343 } 344 345 /** 346 * Gets an iterator that provides an iterator view of the given enumeration 347 * that will remove elements from the specified collection. 348 * 349 * @param <E> the element type 350 * @param enumeration the enumeration to use, may not be null 351 * @param removeCollection the collection to remove elements from, may not be null 352 * @return a new iterator 353 * @throws NullPointerException if enumeration or removeCollection is null 354 */ 355 public static <E> Iterator<E> asIterator(final Enumeration<? extends E> enumeration, 356 final Collection<? super E> removeCollection) { 357 return new EnumerationIterator<>(Objects.requireNonNull(enumeration, "enumeration"), 358 Objects.requireNonNull(removeCollection, "removeCollection")); 359 } 360 361 /** 362 * Gets an iterable that wraps an iterator. The returned iterable can be 363 * used for multiple iterations. 364 * 365 * @param <E> the element type 366 * @param iterator the iterator to use, may not be null 367 * @return a new, multiple use iterable 368 * @throws NullPointerException if iterator is null 369 */ 370 public static <E> Iterable<E> asMultipleUseIterable(final Iterator<? extends E> iterator) { 371 Objects.requireNonNull(iterator, "iterator"); 372 return new IteratorIterable<>(iterator, true); 373 } 374 375 // Bounded 376 /** 377 * Decorates the specified iterator to return at most the given number 378 * of elements. 379 * 380 * @param <E> the element type 381 * @param iterator the iterator to decorate 382 * @param max the maximum number of elements returned by this iterator 383 * @return a new bounded iterator 384 * @throws NullPointerException if the iterator is null 385 * @throws IllegalArgumentException if max is negative 386 * @since 4.1 387 */ 388 public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator, final long max) { 389 return boundedIterator(iterator, 0, max); 390 } 391 392 /** 393 * Decorates the specified iterator to return at most the given number 394 * of elements, skipping all elements until the iterator reaches the 395 * position at {@code offset}. 396 * <p> 397 * The iterator is immediately advanced until it reaches the position at 398 * {@code offset}, incurring O(n) time. 399 * 400 * @param <E> the element type 401 * @param iterator the iterator to decorate 402 * @param offset the index of the first element of the decorated iterator to return 403 * @param max the maximum number of elements returned by this iterator 404 * @return a new bounded iterator 405 * @throws NullPointerException if the iterator is null 406 * @throws IllegalArgumentException if either offset or max is negative 407 * @since 4.1 408 */ 409 public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator, 410 final long offset, final long max) { 411 return new BoundedIterator<>(iterator, offset, max); 412 } 413 414 /** 415 * Gets an iterator that iterates through a collections of {@link Iterator}s 416 * one after another. 417 * 418 * @param <E> the element type 419 * @param iterators the iterators to use, not null or empty or contain nulls 420 * @return a combination iterator over the iterators 421 * @throws NullPointerException if iterators collection is null or contains a null 422 * @throws ClassCastException if the iterators collection contains the wrong object type 423 */ 424 public static <E> Iterator<E> chainedIterator(final Collection<Iterator<? extends E>> iterators) { 425 return new IteratorChain<>(iterators); 426 } 427 428 /** 429 * Gets an iterator that iterates through an array of {@link Iterator}s 430 * one after another. 431 * 432 * @param <E> the element type 433 * @param iterators the iterators to use, not null or empty or contain nulls 434 * @return a combination iterator over the iterators 435 * @throws NullPointerException if iterators array is null or contains a null 436 */ 437 public static <E> Iterator<E> chainedIterator(final Iterator<? extends E>... iterators) { 438 return new IteratorChain<>(iterators); 439 } 440 441 /** 442 * Gets an iterator that iterates through two {@link Iterator}s 443 * one after another. 444 * 445 * @param <E> the element type 446 * @param iterator1 the first iterator to use, not null 447 * @param iterator2 the second iterator to use, not null 448 * @return a combination iterator over the iterators 449 * @throws NullPointerException if either iterator is null 450 */ 451 public static <E> Iterator<E> chainedIterator(final Iterator<? extends E> iterator1, 452 final Iterator<? extends E> iterator2) { 453 // keep a version with two iterators to avoid the following warning in client code (Java 5 & 6) 454 // "A generic array of E is created for a varargs parameter" 455 return new IteratorChain<>(iterator1, iterator2); 456 } 457 458 /** 459 * Gets an iterator that provides an ordered iteration over the elements 460 * contained in a collection of {@link Iterator}s. 461 * <p> 462 * Given two ordered {@link Iterator}s {@code A} and {@code B}, 463 * the {@link Iterator#next()} method will return the lesser of 464 * {@code A.next()} and {@code B.next()} and so on. 465 * <p> 466 * The comparator is optional. If null is specified then natural order is used. 467 * 468 * @param <E> the element type 469 * @param comparator the comparator to use, may be null for natural order 470 * @param iterators the iterators to use, not null or empty or contain nulls 471 * @return a combination iterator over the iterators 472 * @throws NullPointerException if iterators collection is null or contains a null 473 * @throws ClassCastException if the iterators collection contains the wrong object type 474 */ 475 public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator, 476 final Collection<Iterator<? extends E>> iterators) { 477 @SuppressWarnings("unchecked") 478 final Comparator<E> comp = 479 comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator; 480 return new CollatingIterator<>(comp, iterators); 481 } 482 483 /** 484 * Gets an iterator that provides an ordered iteration over the elements 485 * contained in an array of {@link Iterator}s. 486 * <p> 487 * Given two ordered {@link Iterator}s {@code A} and {@code B}, 488 * the {@link Iterator#next()} method will return the lesser of 489 * {@code A.next()} and {@code B.next()} and so on. 490 * <p> 491 * The comparator is optional. If null is specified then natural order is used. 492 * 493 * @param <E> the element type 494 * @param comparator the comparator to use, may be null for natural order 495 * @param iterators the iterators to use, not null or empty or contain nulls 496 * @return a combination iterator over the iterators 497 * @throws NullPointerException if iterators array is null or contains a null value 498 */ 499 public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator, 500 final Iterator<? extends E>... iterators) { 501 @SuppressWarnings("unchecked") 502 final Comparator<E> comp = 503 comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator; 504 return new CollatingIterator<>(comp, iterators); 505 } 506 507 // Collated 508 /** 509 * Gets an iterator that provides an ordered iteration over the elements 510 * contained in a collection of ordered {@link Iterator}s. 511 * <p> 512 * Given two ordered {@link Iterator}s {@code A} and {@code B}, 513 * the {@link Iterator#next()} method will return the lesser of 514 * {@code A.next()} and {@code B.next()}. 515 * <p> 516 * The comparator is optional. If null is specified then natural order is used. 517 * 518 * @param <E> the element type 519 * @param comparator the comparator to use, may be null for natural order 520 * @param iterator1 the first iterators to use, not null 521 * @param iterator2 the first iterators to use, not null 522 * @return a combination iterator over the iterators 523 * @throws NullPointerException if either iterator is null 524 */ 525 public static <E> Iterator<E> collatedIterator(final Comparator<? super E> comparator, 526 final Iterator<? extends E> iterator1, 527 final Iterator<? extends E> iterator2) { 528 @SuppressWarnings("unchecked") 529 final Comparator<E> comp = 530 comparator == null ? ComparatorUtils.NATURAL_COMPARATOR : (Comparator<E>) comparator; 531 return new CollatingIterator<>(comp, iterator1, iterator2); 532 } 533 534 // Chained 535 536 /** 537 * Checks if the object is contained in the given iterator. 538 * <p> 539 * A {@code null} or empty iterator returns false. 540 * 541 * @param <E> the type of object the {@link Iterator} contains 542 * @param iterator the iterator to check, may be null 543 * @param object the object to check 544 * @return true if the object is contained in the iterator, false otherwise 545 * @since 4.1 546 */ 547 public static <E> boolean contains(final Iterator<E> iterator, final Object object) { 548 return matchesAny(iterator, EqualPredicate.equalPredicate(object)); 549 } 550 551 // Empty 552 /** 553 * Gets an empty iterator. 554 * <p> 555 * This iterator is a valid iterator object that will iterate over nothing. 556 * 557 * @param <E> the element type 558 * @return an iterator over nothing 559 */ 560 public static <E> ResettableIterator<E> emptyIterator() { 561 return EmptyIterator.<E>resettableEmptyIterator(); 562 } 563 564 /** 565 * Gets an empty list iterator. 566 * <p> 567 * This iterator is a valid list iterator object that will iterate 568 * over nothing. 569 * 570 * @param <E> the element type 571 * @return a list iterator over nothing 572 */ 573 public static <E> ResettableListIterator<E> emptyListIterator() { 574 return EmptyListIterator.<E>resettableEmptyListIterator(); 575 } 576 577 /** 578 * Gets an empty map iterator. 579 * <p> 580 * This iterator is a valid map iterator object that will iterate 581 * over nothing. 582 * 583 * @param <K> the key type 584 * @param <V> the value type 585 * @return a map iterator over nothing 586 */ 587 public static <K, V> MapIterator<K, V> emptyMapIterator() { 588 return EmptyMapIterator.<K, V>emptyMapIterator(); 589 } 590 591 /** 592 * Gets an empty ordered iterator. 593 * <p> 594 * This iterator is a valid iterator object that will iterate 595 * over nothing. 596 * 597 * @param <E> the element type 598 * @return an ordered iterator over nothing 599 */ 600 public static <E> OrderedIterator<E> emptyOrderedIterator() { 601 return EmptyOrderedIterator.<E>emptyOrderedIterator(); 602 } 603 604 /** 605 * Gets an empty ordered map iterator. 606 * <p> 607 * This iterator is a valid map iterator object that will iterate 608 * over nothing. 609 * 610 * @param <K> the key type 611 * @param <V> the value type 612 * @return a map iterator over nothing 613 */ 614 public static <K, V> OrderedMapIterator<K, V> emptyOrderedMapIterator() { 615 return EmptyOrderedMapIterator.<K, V>emptyOrderedMapIterator(); 616 } 617 618 // Filtered 619 /** 620 * Gets an iterator that filters another iterator. 621 * <p> 622 * The returned iterator will only return objects that match the specified 623 * filtering predicate. 624 * 625 * @param <E> the element type 626 * @param iterator the iterator to use, not null 627 * @param predicate the predicate to use as a filter, not null 628 * @return a new filtered iterator 629 * @throws NullPointerException if either parameter is null 630 */ 631 public static <E> Iterator<E> filteredIterator(final Iterator<? extends E> iterator, 632 final Predicate<? super E> predicate) { 633 Objects.requireNonNull(iterator, "iterator"); 634 Objects.requireNonNull(predicate, "predicate"); 635 return new FilterIterator<>(iterator, predicate); 636 } 637 638 /** 639 * Gets a list iterator that filters another list iterator. 640 * <p> 641 * The returned iterator will only return objects that match the specified 642 * filtering predicate. 643 * 644 * @param <E> the element type 645 * @param listIterator the list iterator to use, not null 646 * @param predicate the predicate to use as a filter, not null 647 * @return a new filtered iterator 648 * @throws NullPointerException if either parameter is null 649 */ 650 public static <E> ListIterator<E> filteredListIterator(final ListIterator<? extends E> listIterator, 651 final Predicate<? super E> predicate) { 652 653 Objects.requireNonNull(listIterator, "listIterator"); 654 Objects.requireNonNull(predicate, "predicate"); 655 return new FilterListIterator<>(listIterator, predicate); 656 } 657 658 /** 659 * Finds the first element in the given iterator which matches the given predicate. 660 * <p> 661 * A {@code null} or empty iterator returns null. 662 * 663 * @param <E> the element type 664 * @param iterator the iterator to search, may be null 665 * @param predicate the predicate to use, must not be null 666 * @return the first element of the iterator which matches the predicate or null if none could be found 667 * @throws NullPointerException if predicate is null 668 * @since 4.1 669 */ 670 public static <E> E find(final Iterator<E> iterator, final Predicate<? super E> predicate) { 671 Objects.requireNonNull(predicate, "predicate"); 672 673 if (iterator != null) { 674 while (iterator.hasNext()) { 675 final E element = iterator.next(); 676 if (predicate.evaluate(element)) { 677 return element; 678 } 679 } 680 } 681 return null; 682 } 683 684 /** 685 * Shortcut for {@code get(iterator, 0)}. 686 * <p> 687 * Returns the {@code first} value in {@link Iterator}, throwing 688 * {@code IndexOutOfBoundsException} if there is no such element. 689 * </p> 690 * <p> 691 * The Iterator is advanced to {@code 0} (or to the end, if 692 * {@code 0} exceeds the number of entries) as a side effect of this method. 693 * </p> 694 * @param <E> the type of object in the {@link Iterator} 695 * @param iterator the iterator to get a value from 696 * @return the first object 697 * @throws IndexOutOfBoundsException if the request is invalid 698 * @since 4.2 699 */ 700 public static <E> E first(final Iterator<E> iterator) { 701 return get(iterator, 0); 702 } 703 704 /** 705 * Applies the closure to each element of the provided iterator. 706 * 707 * @param <E> the element type 708 * @param iterator the iterator to use, may be null 709 * @param closure the closure to apply to each element, may not be null 710 * @throws NullPointerException if closure is null 711 * @since 4.1 712 */ 713 public static <E> void forEach(final Iterator<E> iterator, final Closure<? super E> closure) { 714 Objects.requireNonNull(closure, "closure"); 715 716 if (iterator != null) { 717 while (iterator.hasNext()) { 718 final E element = iterator.next(); 719 closure.execute(element); 720 } 721 } 722 } 723 724 /** 725 * Executes the given closure on each but the last element in the iterator. 726 * <p> 727 * If the input iterator is null no change is made. 728 * 729 * @param <E> the type of object the {@link Iterator} contains 730 * @param iterator the iterator to get the input from, may be null 731 * @param closure the closure to perform, may not be null 732 * @return the last element in the iterator, or null if iterator is null or empty 733 * @throws NullPointerException if closure is null 734 * @since 4.1 735 */ 736 public static <E> E forEachButLast(final Iterator<E> iterator, final Closure<? super E> closure) { 737 Objects.requireNonNull(closure, "closure"); 738 739 if (iterator != null) { 740 while (iterator.hasNext()) { 741 final E element = iterator.next(); 742 if (!iterator.hasNext()) { 743 return element; 744 } 745 closure.execute(element); 746 } 747 } 748 return null; 749 } 750 751 /** 752 * Returns the {@code index}-th value in {@link Iterator}, throwing 753 * {@code IndexOutOfBoundsException} if there is no such element. 754 * <p> 755 * The Iterator is advanced to {@code index} (or to the end, if 756 * {@code index} exceeds the number of entries) as a side effect of this method. 757 * 758 * @param <E> the type of object in the {@link Iterator} 759 * @param iterator the iterator to get a value from 760 * @param index the index to get 761 * @return the object at the specified index 762 * @throws IndexOutOfBoundsException if the index is invalid 763 * @since 4.1 764 */ 765 public static <E> E get(final Iterator<E> iterator, final int index) { 766 int i = index; 767 CollectionUtils.checkIndexBounds(i); 768 while (iterator.hasNext()) { 769 i--; 770 if (i == -1) { 771 return iterator.next(); 772 } 773 iterator.next(); 774 } 775 throw new IndexOutOfBoundsException("Entry does not exist: " + i); 776 } 777 778 /** 779 * Gets a suitable Iterator for the given object. 780 * <p> 781 * This method can handle objects as follows 782 * <ul> 783 * <li>null - empty iterator 784 * <li>Iterator - returned directly 785 * <li>Enumeration - wrapped 786 * <li>Collection - iterator from collection returned 787 * <li>Map - values iterator returned 788 * <li>Dictionary - values (elements) enumeration returned as iterator 789 * <li>array - iterator over array returned 790 * <li>object with iterator() public method accessed by reflection 791 * <li>object - singleton iterator 792 * <li>NodeList - iterator over the list 793 * <li>Node - iterator over the child nodes 794 * </ul> 795 * 796 * @param obj the object to convert to an iterator 797 * @return a suitable iterator, never null 798 */ 799 public static Iterator<?> getIterator(final Object obj) { 800 if (obj == null) { 801 return emptyIterator(); 802 } 803 if (obj instanceof Iterator) { 804 return (Iterator<?>) obj; 805 } 806 if (obj instanceof Iterable) { 807 return ((Iterable<?>) obj).iterator(); 808 } 809 if (obj instanceof Object[]) { 810 return new ObjectArrayIterator<>((Object[]) obj); 811 } 812 if (obj instanceof Enumeration) { 813 return new EnumerationIterator<>((Enumeration<?>) obj); 814 } 815 if (obj instanceof Map) { 816 return ((Map<?, ?>) obj).values().iterator(); 817 } 818 if (obj instanceof NodeList) { 819 return new NodeListIterator((NodeList) obj); 820 } 821 if (obj instanceof Node) { 822 return new NodeListIterator((Node) obj); 823 } 824 if (obj instanceof Dictionary) { 825 return new EnumerationIterator<>(((Dictionary<?, ?>) obj).elements()); 826 } 827 if (obj.getClass().isArray()) { 828 return new ArrayIterator<>(obj); 829 } 830 try { 831 final Method method = obj.getClass().getMethod("iterator", (Class[]) null); 832 if (Iterator.class.isAssignableFrom(method.getReturnType())) { 833 final Iterator<?> it = (Iterator<?>) method.invoke(obj, (Object[]) null); 834 if (it != null) { 835 return it; 836 } 837 } 838 } catch (final RuntimeException | ReflectiveOperationException ignore) { // NOPMD 839 // ignore 840 } 841 return singletonIterator(obj); 842 } 843 844 // Peeking 845 846 /** 847 * Returns the index of the first element in the specified iterator that 848 * matches the given predicate. 849 * <p> 850 * A {@code null} or empty iterator returns -1. 851 * 852 * @param <E> the element type 853 * @param iterator the iterator to search, may be null 854 * @param predicate the predicate to use, may not be null 855 * @return the index of the first element which matches the predicate or -1 if none matches 856 * @throws NullPointerException if predicate is null 857 * @since 4.1 858 */ 859 public static <E> int indexOf(final Iterator<E> iterator, final Predicate<? super E> predicate) { 860 Objects.requireNonNull(predicate, "predicate"); 861 862 if (iterator != null) { 863 for (int index = 0; iterator.hasNext(); index++) { 864 final E element = iterator.next(); 865 if (predicate.evaluate(element)) { 866 return index; 867 } 868 } 869 } 870 return CollectionUtils.INDEX_NOT_FOUND; 871 } 872 873 // Pushback 874 875 /** 876 * Checks if the given iterator is empty. 877 * <p> 878 * A {@code null} or empty iterator returns true. 879 * 880 * @param iterator the {@link Iterator} to use, may be null 881 * @return true if the iterator is exhausted or null, false otherwise 882 * @since 4.1 883 */ 884 public static boolean isEmpty(final Iterator<?> iterator) { 885 return iterator == null || !iterator.hasNext(); 886 } 887 888 // Looping 889 /** 890 * Gets an iterator that loops continuously over the supplied collection. 891 * <p> 892 * The iterator will only stop looping if the remove method is called 893 * enough times to empty the collection, or if the collection is empty 894 * to start with. 895 * 896 * @param <E> the element type 897 * @param collection the collection to iterate over, not null 898 * @return a new looping iterator 899 * @throws NullPointerException if the collection is null 900 */ 901 public static <E> ResettableIterator<E> loopingIterator(final Collection<? extends E> collection) { 902 return new LoopingIterator<>(Objects.requireNonNull(collection, "collection")); 903 } 904 905 /** 906 * Gets an iterator that loops continuously over the supplied list. 907 * <p> 908 * The iterator will only stop looping if the remove method is called 909 * enough times to empty the list, or if the list is empty to start with. 910 * 911 * @param <E> the element type 912 * @param list the list to iterate over, not null 913 * @return a new looping iterator 914 * @throws NullPointerException if the list is null 915 * @since 3.2 916 */ 917 public static <E> ResettableListIterator<E> loopingListIterator(final List<E> list) { 918 return new LoopingListIterator<>(Objects.requireNonNull(list, "list")); 919 } 920 921 /** 922 * Answers true if a predicate is true for every element of an iterator. 923 * <p> 924 * A {@code null} or empty iterator returns true. 925 * 926 * @param <E> the type of object the {@link Iterator} contains 927 * @param iterator the {@link Iterator} to use, may be null 928 * @param predicate the predicate to use, may not be null 929 * @return true if every element of the collection matches the predicate or if the 930 * collection is empty, false otherwise 931 * @throws NullPointerException if predicate is null 932 * @since 4.1 933 */ 934 public static <E> boolean matchesAll(final Iterator<E> iterator, final Predicate<? super E> predicate) { 935 Objects.requireNonNull(predicate, "predicate"); 936 937 if (iterator != null) { 938 while (iterator.hasNext()) { 939 final E element = iterator.next(); 940 if (!predicate.evaluate(element)) { 941 return false; 942 } 943 } 944 } 945 return true; 946 } 947 948 /** 949 * Answers true if a predicate is true for any element of the iterator. 950 * <p> 951 * A {@code null} or empty iterator returns false. 952 * 953 * @param <E> the type of object the {@link Iterator} contains 954 * @param iterator the {@link Iterator} to use, may be null 955 * @param predicate the predicate to use, may not be null 956 * @return true if any element of the collection matches the predicate, false otherwise 957 * @throws NullPointerException if predicate is null 958 * @since 4.1 959 */ 960 public static <E> boolean matchesAny(final Iterator<E> iterator, final Predicate<? super E> predicate) { 961 return indexOf(iterator, predicate) != -1; 962 } 963 964 /** 965 * Gets an {@link Iterator} that wraps the specified node's childNodes. 966 * The returned {@link Iterator} can be used for a single iteration. 967 * <p> 968 * Convenience method, allows easy iteration over NodeLists: 969 * <pre> 970 * Iterator<Node> iterator = IteratorUtils.nodeListIterator(node); 971 * for (Node childNode : IteratorUtils.asIterable(iterator)) { 972 * ... 973 * } 974 * </pre> 975 * 976 * @param node the node to use, may not be null 977 * @return a new, single use {@link Iterator} 978 * @throws NullPointerException if node is null 979 * @since 4.0 980 */ 981 public static NodeListIterator nodeListIterator(final Node node) { 982 return new NodeListIterator(Objects.requireNonNull(node, "node")); 983 } 984 985 // org.w3c.dom.NodeList iterators 986 /** 987 * Gets an {@link Iterator} that wraps the specified {@link NodeList}. 988 * The returned {@link Iterator} can be used for a single iteration. 989 * 990 * @param nodeList the node list to use, may not be null 991 * @return a new, single use {@link Iterator} 992 * @throws NullPointerException if nodeList is null 993 * @since 4.0 994 */ 995 public static NodeListIterator nodeListIterator(final NodeList nodeList) { 996 return new NodeListIterator(Objects.requireNonNull(nodeList, "nodeList")); 997 } 998 999 // Object Graph 1000 /** 1001 * Gets an iterator that operates over an object graph. 1002 * <p> 1003 * This iterator can extract multiple objects from a complex tree-like object graph. 1004 * The iteration starts from a single root object. 1005 * It uses a {@code Transformer} to extract the iterators and elements. 1006 * Its main benefit is that no intermediate {@code List} is created. 1007 * <p> 1008 * For example, consider an object graph: 1009 * <pre> 1010 * |- Branch -- Leaf 1011 * | \- Leaf 1012 * |- Tree | /- Leaf 1013 * | |- Branch -- Leaf 1014 * Forest | \- Leaf 1015 * | |- Branch -- Leaf 1016 * | | \- Leaf 1017 * |- Tree | /- Leaf 1018 * |- Branch -- Leaf 1019 * |- Branch -- Leaf</pre> 1020 * The following {@code Transformer}, used in this class, will extract all 1021 * the Leaf objects without creating a combined intermediate list: 1022 * <pre> 1023 * public Object transform(Object input) { 1024 * if (input instanceof Forest) { 1025 * return ((Forest) input).treeIterator(); 1026 * } 1027 * if (input instanceof Tree) { 1028 * return ((Tree) input).branchIterator(); 1029 * } 1030 * if (input instanceof Branch) { 1031 * return ((Branch) input).leafIterator(); 1032 * } 1033 * if (input instanceof Leaf) { 1034 * return input; 1035 * } 1036 * throw new ClassCastException(); 1037 * }</pre> 1038 * <p> 1039 * Internally, iteration starts from the root object. When next is called, 1040 * the transformer is called to examine the object. The transformer will return 1041 * either an iterator or an object. If the object is an Iterator, the next element 1042 * from that iterator is obtained and the process repeats. If the element is an object 1043 * it is returned. 1044 * <p> 1045 * Under many circumstances, linking Iterators together in this manner is 1046 * more efficient (and convenient) than using nested for loops to extract a list. 1047 * 1048 * @param <E> the element type 1049 * @param root the root object to start iterating from, null results in an empty iterator 1050 * @param transformer the transformer to use, see above, null uses no effect transformer 1051 * @return a new object graph iterator 1052 * @since 3.1 1053 */ 1054 public static <E> Iterator<E> objectGraphIterator(final E root, 1055 final Transformer<? super E, ? extends E> transformer) { 1056 return new ObjectGraphIterator<>(root, transformer); 1057 } 1058 1059 /** 1060 * Gets an iterator that supports one-element lookahead. 1061 * 1062 * @param <E> the element type 1063 * @param iterator the iterator to decorate, not null 1064 * @return a peeking iterator 1065 * @throws NullPointerException if the iterator is null 1066 * @since 4.0 1067 */ 1068 public static <E> Iterator<E> peekingIterator(final Iterator<? extends E> iterator) { 1069 return PeekingIterator.peekingIterator(iterator); 1070 } 1071 1072 /** 1073 * Gets an iterator that supports pushback of elements. 1074 * 1075 * @param <E> the element type 1076 * @param iterator the iterator to decorate, not null 1077 * @return a pushback iterator 1078 * @throws NullPointerException if the iterator is null 1079 * @since 4.0 1080 */ 1081 public static <E> Iterator<E> pushbackIterator(final Iterator<? extends E> iterator) { 1082 return PushbackIterator.pushbackIterator(iterator); 1083 } 1084 1085 // Singleton 1086 /** 1087 * Gets a singleton iterator. 1088 * <p> 1089 * This iterator is a valid iterator object that will iterate over 1090 * the specified object. 1091 * 1092 * @param <E> the element type 1093 * @param object the single object over which to iterate 1094 * @return a singleton iterator over the object 1095 */ 1096 public static <E> ResettableIterator<E> singletonIterator(final E object) { 1097 return new SingletonIterator<>(object); 1098 } 1099 1100 /** 1101 * Gets a singleton list iterator. 1102 * <p> 1103 * This iterator is a valid list iterator object that will iterate over 1104 * the specified object. 1105 * 1106 * @param <E> the element type 1107 * @param object the single object over which to iterate 1108 * @return a singleton list iterator over the object 1109 */ 1110 public static <E> ListIterator<E> singletonListIterator(final E object) { 1111 return new SingletonListIterator<>(object); 1112 } 1113 1114 /** 1115 * Returns the number of elements contained in the given iterator. 1116 * <p> 1117 * A {@code null} or empty iterator returns {@code 0}. 1118 * 1119 * @param iterator the iterator to check, may be null 1120 * @return the number of elements contained in the iterator 1121 * @since 4.1 1122 */ 1123 public static int size(final Iterator<?> iterator) { 1124 int size = 0; 1125 if (iterator != null) { 1126 while (iterator.hasNext()) { 1127 iterator.next(); 1128 size++; 1129 } 1130 } 1131 return size; 1132 } 1133 1134 // Skipping 1135 /** 1136 * Decorates the specified iterator to skip the first N elements. 1137 * 1138 * @param <E> the element type 1139 * @param iterator the iterator to decorate 1140 * @param offset the first number of elements to skip 1141 * @return a new skipping iterator 1142 * @throws NullPointerException if the iterator is null 1143 * @throws IllegalArgumentException if offset is negative 1144 * @since 4.1 1145 */ 1146 public static <E> SkippingIterator<E> skippingIterator(final Iterator<E> iterator, final long offset) { 1147 return new SkippingIterator<>(iterator, offset); 1148 } 1149 1150 /** 1151 * Gets an array based on an iterator. 1152 * <p> 1153 * As the wrapped Iterator is traversed, an ArrayList of its values is 1154 * created. At the end, this is converted to an array. 1155 * 1156 * @param iterator the iterator to use, not null 1157 * @return an array of the iterator contents 1158 * @throws NullPointerException if iterator parameter is null 1159 */ 1160 public static Object[] toArray(final Iterator<?> iterator) { 1161 Objects.requireNonNull(iterator, "iterator"); 1162 final List<?> list = toList(iterator, 100); 1163 return list.toArray(); 1164 } 1165 1166 /** 1167 * Gets an array based on an iterator. 1168 * <p> 1169 * As the wrapped Iterator is traversed, an ArrayList of its values is 1170 * created. At the end, this is converted to an array. 1171 * 1172 * @param <E> the element type 1173 * @param iterator the iterator to use, not null 1174 * @param arrayClass the class of array to create 1175 * @return an array of the iterator contents 1176 * @throws NullPointerException if iterator parameter or arrayClass is null 1177 * @throws ArrayStoreException if the arrayClass is invalid 1178 */ 1179 public static <E> E[] toArray(final Iterator<? extends E> iterator, final Class<E> arrayClass) { 1180 Objects.requireNonNull(iterator, "iterator"); 1181 Objects.requireNonNull(arrayClass, "arrayClass"); 1182 final List<E> list = toList(iterator, 100); 1183 @SuppressWarnings("unchecked") 1184 final E[] array = (E[]) Array.newInstance(arrayClass, list.size()); 1185 return list.toArray(array); 1186 } 1187 1188 // Utility methods 1189 1190 /** 1191 * Gets a list based on an iterator. 1192 * <p> 1193 * As the wrapped Iterator is traversed, an ArrayList of its values is 1194 * created. At the end, the list is returned. 1195 * 1196 * @param <E> the element type 1197 * @param iterator the iterator to use, not null 1198 * @return a list of the iterator contents 1199 * @throws NullPointerException if iterator parameter is null 1200 */ 1201 public static <E> List<E> toList(final Iterator<? extends E> iterator) { 1202 return toList(iterator, 10); 1203 } 1204 1205 /** 1206 * Gets a list based on an iterator. 1207 * <p> 1208 * As the wrapped Iterator is traversed, an ArrayList of its values is 1209 * created. At the end, the list is returned. 1210 * 1211 * @param <E> the element type 1212 * @param iterator the iterator to use, not null 1213 * @param estimatedSize the initial size of the ArrayList 1214 * @return a list of the iterator contents 1215 * @throws NullPointerException if iterator parameter is null 1216 * @throws IllegalArgumentException if the size is less than 1 1217 */ 1218 public static <E> List<E> toList(final Iterator<? extends E> iterator, final int estimatedSize) { 1219 Objects.requireNonNull(iterator, "iterator"); 1220 if (estimatedSize < 1) { 1221 throw new IllegalArgumentException("Estimated size must be greater than 0"); 1222 } 1223 final List<E> list = new ArrayList<>(estimatedSize); 1224 while (iterator.hasNext()) { 1225 list.add(iterator.next()); 1226 } 1227 return list; 1228 } 1229 1230 /** 1231 * Gets a list iterator based on a simple iterator. 1232 * <p> 1233 * As the wrapped Iterator is traversed, a LinkedList of its values is 1234 * cached, permitting all required operations of ListIterator. 1235 * 1236 * @param <E> the element type 1237 * @param iterator the iterator to use, may not be null 1238 * @return a new iterator 1239 * @throws NullPointerException if iterator parameter is null 1240 */ 1241 public static <E> ListIterator<E> toListIterator(final Iterator<? extends E> iterator) { 1242 Objects.requireNonNull(iterator, "iterator"); 1243 return new ListIteratorWrapper<>(iterator); 1244 } 1245 1246 /** 1247 * Returns a string representation of the elements of the specified iterator. 1248 * <p> 1249 * The string representation consists of a list of the iterator's elements, 1250 * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated 1251 * by the characters {@code ", "} (a comma followed by a space). Elements are 1252 * converted to strings as by {@code String.valueOf(Object)}. 1253 * 1254 * @param <E> the element type 1255 * @param iterator the iterator to convert to a string, may be null 1256 * @return a string representation of {@code iterator} 1257 * @since 4.1 1258 */ 1259 public static <E> String toString(final Iterator<E> iterator) { 1260 return toString(iterator, TransformerUtils.stringValueTransformer(), 1261 DEFAULT_TOSTRING_DELIMITER, CollectionUtils.DEFAULT_TOSTRING_PREFIX, 1262 CollectionUtils.DEFAULT_TOSTRING_SUFFIX); 1263 } 1264 1265 /** 1266 * Returns a string representation of the elements of the specified iterator. 1267 * <p> 1268 * The string representation consists of a list of the iterable's elements, 1269 * enclosed in square brackets ({@code "[]"}). Adjacent elements are separated 1270 * by the characters {@code ", "} (a comma followed by a space). Elements are 1271 * converted to strings as by using the provided {@code transformer}. 1272 * 1273 * @param <E> the element type 1274 * @param iterator the iterator to convert to a string, may be null 1275 * @param transformer the transformer used to get a string representation of an element 1276 * @return a string representation of {@code iterator} 1277 * @throws NullPointerException if {@code transformer} is null 1278 * @since 4.1 1279 */ 1280 public static <E> String toString(final Iterator<E> iterator, 1281 final Transformer<? super E, String> transformer) { 1282 return toString(iterator, transformer, DEFAULT_TOSTRING_DELIMITER, 1283 CollectionUtils.DEFAULT_TOSTRING_PREFIX, CollectionUtils.DEFAULT_TOSTRING_SUFFIX); 1284 } 1285 1286 /** 1287 * Returns a string representation of the elements of the specified iterator. 1288 * <p> 1289 * The string representation consists of a list of the iterator's elements, 1290 * enclosed by the provided {@code prefix} and {@code suffix}. Adjacent elements 1291 * are separated by the provided {@code delimiter}. Elements are converted to 1292 * strings as by using the provided {@code transformer}. 1293 * 1294 * @param <E> the element type 1295 * @param iterator the iterator to convert to a string, may be null 1296 * @param transformer the transformer used to get a string representation of an element 1297 * @param delimiter the string to delimit elements 1298 * @param prefix the prefix, prepended to the string representation 1299 * @param suffix the suffix, appended to the string representation 1300 * @return a string representation of {@code iterator} 1301 * @throws NullPointerException if either transformer, delimiter, prefix or suffix is null 1302 * @since 4.1 1303 */ 1304 public static <E> String toString(final Iterator<E> iterator, 1305 final Transformer<? super E, String> transformer, 1306 final String delimiter, 1307 final String prefix, 1308 final String suffix) { 1309 Objects.requireNonNull(transformer, "transformer"); 1310 Objects.requireNonNull(delimiter, "delimiter"); 1311 Objects.requireNonNull(prefix, "prefix"); 1312 Objects.requireNonNull(suffix, "suffix"); 1313 final StringBuilder stringBuilder = new StringBuilder(prefix); 1314 if (iterator != null) { 1315 while (iterator.hasNext()) { 1316 final E element = iterator.next(); 1317 stringBuilder.append(transformer.transform(element)); 1318 stringBuilder.append(delimiter); 1319 } 1320 if (stringBuilder.length() > prefix.length()) { 1321 stringBuilder.setLength(stringBuilder.length() - delimiter.length()); 1322 } 1323 } 1324 stringBuilder.append(suffix); 1325 return stringBuilder.toString(); 1326 } 1327 1328 // Transformed 1329 /** 1330 * Gets an iterator that transforms the elements of another iterator. 1331 * <p> 1332 * The transformation occurs during the next() method and the underlying 1333 * iterator is unaffected by the transformation. 1334 * 1335 * @param <I> the input type 1336 * @param <O> the output type 1337 * @param iterator the iterator to use, not null 1338 * @param transformer the transform to use, not null 1339 * @return a new transforming iterator 1340 * @throws NullPointerException if either parameter is null 1341 */ 1342 public static <I, O> Iterator<O> transformedIterator(final Iterator<? extends I> iterator, 1343 final Transformer<? super I, ? extends O> transformer) { 1344 1345 Objects.requireNonNull(iterator, "iterator"); 1346 Objects.requireNonNull(transformer, "transformer"); 1347 return new TransformIterator<>(iterator, transformer); 1348 } 1349 1350 // Unmodifiable 1351 /** 1352 * Gets an immutable version of an {@link Iterator}. The returned object 1353 * will always throw an {@link UnsupportedOperationException} for 1354 * the {@link Iterator#remove} method. 1355 * 1356 * @param <E> the element type 1357 * @param iterator the iterator to make immutable 1358 * @return an immutable version of the iterator 1359 */ 1360 public static <E> Iterator<E> unmodifiableIterator(final Iterator<E> iterator) { 1361 return UnmodifiableIterator.unmodifiableIterator(iterator); 1362 } 1363 1364 /** 1365 * Gets an immutable version of a {@link ListIterator}. The returned object 1366 * will always throw an {@link UnsupportedOperationException} for 1367 * the {@link Iterator#remove}, {@link ListIterator#add} and 1368 * {@link ListIterator#set} methods. 1369 * 1370 * @param <E> the element type 1371 * @param listIterator the iterator to make immutable 1372 * @return an immutable version of the iterator 1373 */ 1374 public static <E> ListIterator<E> unmodifiableListIterator(final ListIterator<E> listIterator) { 1375 return UnmodifiableListIterator.unmodifiableListIterator(listIterator); 1376 } 1377 1378 /** 1379 * Gets an immutable version of a {@link MapIterator}. The returned object 1380 * will always throw an {@link UnsupportedOperationException} for 1381 * the {@link Iterator#remove}, {@link MapIterator#setValue(Object)} methods. 1382 * 1383 * @param <K> the key type 1384 * @param <V> the value type 1385 * @param mapIterator the iterator to make immutable 1386 * @return an immutable version of the iterator 1387 */ 1388 public static <K, V> MapIterator<K, V> unmodifiableMapIterator(final MapIterator<K, V> mapIterator) { 1389 return UnmodifiableMapIterator.unmodifiableMapIterator(mapIterator); 1390 } 1391 1392 /** 1393 * Returns an iterator that interleaves elements from the decorated iterators. 1394 * 1395 * @param <E> the element type 1396 * @param iterators the array of iterators to interleave 1397 * @return an iterator, interleaving the decorated iterators 1398 * @throws NullPointerException if any iterator is null 1399 * @since 4.1 1400 */ 1401 public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E>... iterators) { 1402 return new ZippingIterator<>(iterators); 1403 } 1404 1405 // Zipping 1406 /** 1407 * Returns an iterator that interleaves elements from the decorated iterators. 1408 * 1409 * @param <E> the element type 1410 * @param a the first iterator to interleave 1411 * @param b the second iterator to interleave 1412 * @return an iterator, interleaving the decorated iterators 1413 * @throws NullPointerException if any iterator is null 1414 * @since 4.1 1415 */ 1416 public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a, 1417 final Iterator<? extends E> b) { 1418 return new ZippingIterator<>(a, b); 1419 } 1420 1421 /** 1422 * Returns an iterator that interleaves elements from the decorated iterators. 1423 * 1424 * @param <E> the element type 1425 * @param a the first iterator to interleave 1426 * @param b the second iterator to interleave 1427 * @param c the third iterator to interleave 1428 * @return an iterator, interleaving the decorated iterators 1429 * @throws NullPointerException if any iterator is null 1430 * @since 4.1 1431 */ 1432 public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E> a, 1433 final Iterator<? extends E> b, 1434 final Iterator<? extends E> c) { 1435 return new ZippingIterator<>(a, b, c); 1436 } 1437 1438 /** 1439 * Don't allow instances. 1440 */ 1441 private IteratorUtils() { 1442 // empty 1443 } 1444 1445}