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