IteratorIterable.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.collections4.iterators;

  18. import java.util.Iterator;

  19. import org.apache.commons.collections4.ResettableIterator;

  20. /**
  21.  * Adapter to make an {@link Iterator Iterator} instance appear to be an
  22.  * {@link Iterable Iterable} instance.  The iterable can be constructed in one
  23.  * of two variants:  single use, multiple use.
  24.  *
  25.  * <p>
  26.  * In the single use iterable case, the iterable is only usable for one
  27.  * iterative operation over the source iterator.  Subsequent iterative
  28.  * operations use the same, exhausted source iterator.  To create a single use
  29.  * iterable, construct a new {@link IteratorIterable} using a {@link Iterator}
  30.  * that is NOT a {@link ResettableIterator} iterator:
  31.  * </p>
  32.  *
  33.  * <pre>
  34.  *   Iterator&lt;Integer&gt; iterator = // some non-resettable iterator
  35.  *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator);
  36.  * </pre>
  37.  *
  38.  * <p>
  39.  * In the multiple use iterable case, the iterable is usable for any number of
  40.  * iterative operations over the source iterator.  Of special note, even though
  41.  * the iterable supports multiple iterations, it does not support concurrent
  42.  * iterations. To implicitly create a multiple use iterable, construct a new
  43.  * {@link IteratorIterable} using a {@link ResettableIterator} iterator:
  44.  * </p>
  45.  *
  46.  * <pre>
  47.  *   Integer[] array = {Integer.valueOf(1),Integer.valueOf(2),Integer.valueOf(3)};
  48.  *   Iterator&lt;Integer&gt; iterator = IteratorUtils.arrayIterator(array); // a resettable iterator
  49.  *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator);
  50.  * </pre>
  51.  *
  52.  * <p>
  53.  * A multiple use iterable can also be explicitly constructed using any
  54.  * {@link Iterator} and specifying {@code true} for the
  55.  * {@code multipleUse} flag:
  56.  * </p>
  57.  *
  58.  * <pre>
  59.  *   Iterator&lt;Integer&gt; iterator = // some non-resettable iterator
  60.  *   Iterable&lt;Integer&gt; iterable = new IteratorIterable&lt;Integer&gt;(iterator, true);
  61.  * </pre>
  62.  *
  63.  * @param <E> the type of elements returned by this iterator.
  64.  * @since 4.0
  65.  */
  66. public class IteratorIterable<E> implements Iterable<E> {

  67.     /**
  68.      * Factory method to create an {@link Iterator Iterator} from another
  69.      * iterator over objects of a different subtype.
  70.      */
  71.     private static <E> Iterator<E> createTypesafeIterator(final Iterator<? extends E> iterator) {
  72.         return new Iterator<E>() {
  73.             @Override
  74.             public boolean hasNext() {
  75.                 return iterator.hasNext();
  76.             }

  77.             @Override
  78.             public E next() {
  79.                 return iterator.next();
  80.             }

  81.             @Override
  82.             public void remove() {
  83.                 iterator.remove();
  84.             }
  85.         };
  86.     }

  87.     /** The iterator being adapted into an iterable. */
  88.     private final Iterator<? extends E> iterator;

  89.     /** The iterator parameterized as the {@link #iterator()} return type. */
  90.     private final Iterator<E> typeSafeIterator;

  91.     /**
  92.      * Constructs a new {@code IteratorIterable} that will use the given
  93.      * iterator.
  94.      *
  95.      * @param iterator the iterator to use.
  96.      */
  97.     public IteratorIterable(final Iterator<? extends E> iterator) {
  98.         this(iterator, false);
  99.     }

  100.     /**
  101.      * Constructs a new {@code IteratorIterable} that will use the given
  102.      * iterator.
  103.      *
  104.      * @param iterator the iterator to use.
  105.      * @param multipleUse {@code true} if the new iterable can be used in multiple iterations
  106.      */
  107.     public IteratorIterable(final Iterator<? extends E> iterator, final boolean multipleUse) {
  108.         if (multipleUse && !(iterator instanceof ResettableIterator)) {
  109.             this.iterator = new ListIteratorWrapper<>(iterator);
  110.         } else {
  111.             this.iterator = iterator;
  112.         }
  113.         this.typeSafeIterator = createTypesafeIterator(this.iterator);
  114.     }

  115.     /**
  116.      * Gets the iterator wrapped by this iterable.
  117.      *
  118.      * @return the iterator
  119.      */
  120.     @Override
  121.     public Iterator<E> iterator() {
  122.         if (iterator instanceof ResettableIterator) {
  123.             ((ResettableIterator<? extends E>) iterator).reset();
  124.         }
  125.         return typeSafeIterator;
  126.     }
  127. }