View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4;
18  
19  import java.lang.reflect.Array;
20  import java.lang.reflect.Method;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Comparator;
24  import java.util.Dictionary;
25  import java.util.Enumeration;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.ListIterator;
29  import java.util.Map;
30  import java.util.Objects;
31  
32  import org.apache.commons.collections4.functors.EqualPredicate;
33  import org.apache.commons.collections4.iterators.ArrayIterator;
34  import org.apache.commons.collections4.iterators.ArrayListIterator;
35  import org.apache.commons.collections4.iterators.BoundedIterator;
36  import org.apache.commons.collections4.iterators.CollatingIterator;
37  import org.apache.commons.collections4.iterators.EmptyIterator;
38  import org.apache.commons.collections4.iterators.EmptyListIterator;
39  import org.apache.commons.collections4.iterators.EmptyMapIterator;
40  import org.apache.commons.collections4.iterators.EmptyOrderedIterator;
41  import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator;
42  import org.apache.commons.collections4.iterators.EnumerationIterator;
43  import org.apache.commons.collections4.iterators.FilterIterator;
44  import org.apache.commons.collections4.iterators.FilterListIterator;
45  import org.apache.commons.collections4.iterators.IteratorChain;
46  import org.apache.commons.collections4.iterators.IteratorEnumeration;
47  import org.apache.commons.collections4.iterators.IteratorIterable;
48  import org.apache.commons.collections4.iterators.ListIteratorWrapper;
49  import org.apache.commons.collections4.iterators.LoopingIterator;
50  import org.apache.commons.collections4.iterators.LoopingListIterator;
51  import org.apache.commons.collections4.iterators.NodeListIterator;
52  import org.apache.commons.collections4.iterators.ObjectArrayIterator;
53  import org.apache.commons.collections4.iterators.ObjectArrayListIterator;
54  import org.apache.commons.collections4.iterators.ObjectGraphIterator;
55  import org.apache.commons.collections4.iterators.PeekingIterator;
56  import org.apache.commons.collections4.iterators.PushbackIterator;
57  import org.apache.commons.collections4.iterators.SingletonIterator;
58  import org.apache.commons.collections4.iterators.SingletonListIterator;
59  import org.apache.commons.collections4.iterators.SkippingIterator;
60  import org.apache.commons.collections4.iterators.TransformIterator;
61  import org.apache.commons.collections4.iterators.UnmodifiableIterator;
62  import org.apache.commons.collections4.iterators.UnmodifiableListIterator;
63  import org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
64  import org.apache.commons.collections4.iterators.ZippingIterator;
65  import org.w3c.dom.Node;
66  import org.w3c.dom.NodeList;
67  
68  /**
69   * Provides static utility methods and decorators for {@link Iterator}
70   * instances. The implementations are provided in the iterators subpackage.
71   *
72   * @since 2.1
73   */
74  public class IteratorUtils {
75      // validation is done in this class in certain cases because the
76      // public classes allow invalid states
77  
78      /**
79       * An iterator over no elements.
80       */
81      @SuppressWarnings("rawtypes")
82      public static final ResettableIterator EMPTY_ITERATOR = EmptyIterator.RESETTABLE_INSTANCE;
83  
84      /**
85       * A list iterator over no elements.
86       */
87      @SuppressWarnings("rawtypes")
88      public static final ResettableListIterator EMPTY_LIST_ITERATOR = EmptyListIterator.RESETTABLE_INSTANCE;
89  
90      /**
91       * An ordered iterator over no elements.
92       */
93      @SuppressWarnings("rawtypes")
94      public static final OrderedIterator EMPTY_ORDERED_ITERATOR = EmptyOrderedIterator.INSTANCE;
95  
96      /**
97       * A map iterator over no elements.
98       */
99      @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&lt;Node&gt; 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 
1443 }