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