You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2024/11/01 22:01:03 UTC

(commons-collections) branch master updated (a0172c8dd -> d591c8578)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git


    from a0172c8dd Added ExtendedIterator and tests #564
     new c4a0d4c27 Use final
     new d591c8578 Refactor ExtendedIterator and FilterIterator with a new interface IteratorOperations

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/changes/changes.xml                            |   1 +
 .../apache/commons/collections4/IteratorUtils.java |  28 ++++
 .../collections4/iterators/ExtendedIterator.java   | 165 +++++++++------------
 .../collections4/iterators/FilterIterator.java     |  14 +-
 .../collections4/iterators/IteratorOperations.java |  88 +++++++++++
 .../iterators/ExtendedIteratorTest.java            | 118 +++++++--------
 .../collections4/iterators/FilterIteratorTest.java |  61 ++++++++
 7 files changed, 311 insertions(+), 164 deletions(-)
 create mode 100644 src/main/java/org/apache/commons/collections4/iterators/IteratorOperations.java


(commons-collections) 02/02: Refactor ExtendedIterator and FilterIterator with a new interface IteratorOperations

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit d591c85785eac742e3192d133a673c0a58baa9e7
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Fri Nov 1 18:00:57 2024 -0400

    Refactor ExtendedIterator and FilterIterator with a new interface
    IteratorOperations
    
    - Inspired by Apache Jena's ExtendedIterator and Claude Warren's
    ExtendedIterator
    - Add missing Javadoc
---
 src/changes/changes.xml                            |   1 +
 .../apache/commons/collections4/IteratorUtils.java |  28 ++++
 .../collections4/iterators/ExtendedIterator.java   | 165 +++++++++------------
 .../collections4/iterators/FilterIterator.java     |  14 +-
 .../collections4/iterators/IteratorOperations.java |  88 +++++++++++
 .../collections4/iterators/FilterIteratorTest.java |  61 ++++++++
 6 files changed, 252 insertions(+), 105 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 009514e3b..ef7095fc2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -61,6 +61,7 @@
     <action type="fix" dev="ggregory" due-to="Gary Gregory">Add missing test AbstractIteratorTest.testForEachRemaining().</action> 
     <action type="fix" dev="ggregory" due-to="Gary Gregory, Claude Warren">Add FilterIterator.removeNext() #564.</action>
     <action type="fix" issue="COLLECTIONS-870" dev="ggregory" due-to="Claude Warren, Gary Gregory">Added ExtendedIterator and tests #564.</action> 
+    <action type="add" dev="ggregory" due-to="Gary Gregory">Refactor ExtendedIterator and FilterIterator with a new interface IteratorOperations.</action>
     <!-- UPDATE -->
     <action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 71 to 78 #534, #545, #550 #555, #566.</action>
     <action type="update" issue="COLLECTIONS-857" dev="ggregory" due-to="Claude Warren">Update bloom filter documentation #508.</action>
diff --git a/src/main/java/org/apache/commons/collections4/IteratorUtils.java b/src/main/java/org/apache/commons/collections4/IteratorUtils.java
index 1b6249204..c8b246b3d 100644
--- a/src/main/java/org/apache/commons/collections4/IteratorUtils.java
+++ b/src/main/java/org/apache/commons/collections4/IteratorUtils.java
@@ -28,7 +28,11 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.function.IntFunction;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import org.apache.commons.collections4.functors.EqualPredicate;
 import org.apache.commons.collections4.iterators.ArrayIterator;
@@ -1226,6 +1230,30 @@ public class IteratorUtils {
         return new SkippingIterator<>(iterator, offset);
     }
 
+    /**
+     * Creates a stream on the given Iterable.
+     *
+     * @param <E> the type of elements in the Iterable.
+     * @param iterable the Iterable to stream or null.
+     * @return a new Stream or {@link Stream#empty()} if the Iterable is null.
+     * @since 4.5.0-M3
+     */
+    public static <E> Stream<E> stream(final Iterable<E> iterable) {
+        return iterable == null ? Stream.empty() : StreamSupport.stream(iterable.spliterator(), false);
+    }
+
+    /**
+     * Creates a stream on the given Iterator.
+     *
+     * @param <E> the type of elements in the Iterator.
+     * @param iterator the Iterator to stream or null.
+     * @return a new Stream or {@link Stream#empty()} if the Iterator is null.
+     * @since 4.5.0-M3
+     */
+    public static <E> Stream<E> stream(final Iterator<E> iterator) {
+        return iterator == null ? Stream.empty() : StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
+    }
+
     /**
      * Gets an array based on an iterator.
      * <p>
diff --git a/src/main/java/org/apache/commons/collections4/iterators/ExtendedIterator.java b/src/main/java/org/apache/commons/collections4/iterators/ExtendedIterator.java
index 7b6733543..662d35b89 100644
--- a/src/main/java/org/apache/commons/collections4/iterators/ExtendedIterator.java
+++ b/src/main/java/org/apache/commons/collections4/iterators/ExtendedIterator.java
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.collections4.iterators;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.function.Consumer;
@@ -24,24 +23,45 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
-
 /**
- * Extends Iterator functionality to include operations commonly found on streams (e.g. filtering, concatenating, mapping).
- * It also provides convenience methods for common operations.
+ * Extends Iterator functionality to include operations commonly found on streams (e.g. filtering, concatenating, mapping). It also provides convenience methods
+ * for common operations.
+ *
  * @param <T> The type of object returned from the iterator.
  * @since 4.5.0-M3
  */
-public final class ExtendedIterator<T> implements Iterator<T> {
+public final class ExtendedIterator<T> implements IteratorOperations<T> {
+
     /**
-     * Set to <code>true</code> if this wrapping doesn't permit the use of
-     * {@link #remove()}, otherwise removal is delegated to the base iterator.
+     * Create an ExtendedIterator returning the elements of <code>it</code>. If <code>it</code> is itself an ExtendedIterator, return that; otherwise wrap
+     * <code>it</code>.
+     *
+     * @param <T> The type of object returned from the iterator.
+     * @param it The iterator to wrap.
+     * @return An Extended iterator wrapping {@code it}
      */
-    private final boolean throwOnRemove;
+    public static <T> ExtendedIterator<T> create(final Iterator<T> it) {
+        return it instanceof ExtendedIterator<?> ? (ExtendedIterator<T>) it : new ExtendedIterator<>(it, false);
+    }
 
     /**
-     * Creates an ExtendedIterator wrapped round <code>it</code>,
-     * which does not permit <code>.remove()</code>
-     * even if <code>it</code> does.
+     * Creates an ExtendedIterator wrapped round a {@link Stream}. The extended iterator does not permit <code>.remove()</code>.
+     * <p>
+     * The stream should not be used directly. The effect of doing so is undefined.
+     * </p>
+     *
+     * @param <T> The type of object returned from the iterator.
+     * @param stream the Stream to create an iterator from.
+     * @return an Extended iterator on the {@code stream} iterator.
+     */
+    public static <T> ExtendedIterator<T> create(final Stream<T> stream) {
+        return new ExtendedIterator<>(stream.iterator(), true);
+    }
+
+    /**
+     * Creates an ExtendedIterator wrapped round <code>it</code>, which does not permit <code>.remove()</code> even if <code>it</code> does.
+     *
+     * @param <T> The type of object returned from the iterator.
      * @param it The Iterator to wrap.
      * @return an Extended iterator on {@code it}
      * @throws UnsupportedOperationException if remove() is called on the resulting iterator.
@@ -51,22 +71,18 @@ public final class ExtendedIterator<T> implements Iterator<T> {
     }
 
     /**
-     * Creates an ExtendedIterator wrapped round a {@link Stream}.
-     * The extended iterator does not permit <code>.remove()</code>.
-     * <p>
-     * The stream should not be used directly. The effect of doing so is
-     * undefined.
-     * </p>
-     * @param stream the Stream to create an iterator from.
-     * @return an Extended iterator on the {@code stream} iterator.
+     * Creates an empty Extended iterator.
+     *
+     * @return An empty Extended iterator.
      */
-    public static <T> ExtendedIterator<T> create(final Stream<T> stream) {
-        return new ExtendedIterator<T>(stream.iterator(), true);
+    public static ExtendedIterator<?> emptyIterator() {
+        return new ExtendedIterator<>(Collections.emptyIterator(), false);
     }
 
     /**
-     * Flattens an iterator of iterators into an Iterator over the next level values.
-     * Similar to list splicing in lisp.
+     * Flattens an iterator of iterators into an Iterator over the next level values. Similar to list splicing in lisp.
+     *
+     * @param <T> The type of object returned from the iterator.
      * @param iterators An iterator of iterators.
      * @return An iterator over the logical concatenation of the inner iterators.
      */
@@ -82,32 +98,17 @@ public final class ExtendedIterator<T> implements Iterator<T> {
     }
 
     /**
-     * Creates an empty Extended iterator.
-     * @return An empty Extended iterator.
-     */
-    public static ExtendedIterator<?> emptyIterator() {
-        return new ExtendedIterator<>(Collections.emptyIterator(), false);
-    }
-
-    /**
-     * Create an ExtendedIterator returning the elements of <code>it</code>.
-     * If <code>it</code> is itself an ExtendedIterator, return that;
-     * otherwise wrap <code>it</code>.
-     * @param it The iterator to wrap.
-     * @return An Extended iterator wrapping {@code it}
+     * Set to <code>true</code> if this wrapping doesn't permit the use of {@link #remove()}, otherwise removal is delegated to the base iterator.
      */
-    public static <T> ExtendedIterator<T> create(final Iterator<T> it) {
-        return it instanceof ExtendedIterator<?>
-                ? (ExtendedIterator<T>) it
-                : new ExtendedIterator<>(it, false);
-    }
+    private final boolean throwOnRemove;
 
-    /** the base iterator that we wrap */
+    /** The base iterator that we wrap */
     private final Iterator<? extends T> base;
 
     /**
-     * Initialise this wrapping with the given base iterator and remove-control.
-     * @param base the base iterator that this iterator wraps
+     * Initialize this wrapping with the given base iterator and remove-control.
+     *
+     * @param base          the base iterator that this iterator wraps
      * @param throwOnRemove true if .remove() must throw an exception
      */
     private ExtendedIterator(final Iterator<? extends T> base, final boolean throwOnRemove) {
@@ -115,41 +116,9 @@ public final class ExtendedIterator<T> implements Iterator<T> {
         this.throwOnRemove = throwOnRemove;
     }
 
-    @Override
-    public boolean hasNext() {
-        return base.hasNext();
-    }
-
-    @Override
-    public T next() {
-        return base.next();
-    }
-
-    @Override
-    public void forEachRemaining(final Consumer<? super T> action) {
-        base.forEachRemaining(action);
-    }
-
-    @Override
-    public void remove() {
-        if (throwOnRemove) {
-            throw new UnsupportedOperationException();
-        }
-        base.remove();
-    }
-
-    /**
-     * Returns the next item and removes it from the iterator.
-     * @return the next item from the iterator.
-     */
-    public T removeNext() {
-        T result = next();
-        remove();
-        return result;
-    }
-
     /**
      * Chains the {@code other} iterator to the end of this one.
+     *
      * @param other the other iterator to extend this iterator with.
      * @return A new iterator returning the contents of {@code this} iterator followed by the contents of {@code other} iterator.
      * @param <X> The type of object returned from the other iterator.
@@ -159,38 +128,50 @@ public final class ExtendedIterator<T> implements Iterator<T> {
             ((IteratorChain<T>) base).addIterator(other);
             return this;
         }
-        return new ExtendedIterator<T>(new IteratorChain<T>(this.base, other), this.throwOnRemove);
+        return new ExtendedIterator<>(new IteratorChain<>(this.base, other), this.throwOnRemove);
     }
 
     /**
-     * Filter this iterator using a predicate.  Only items for which the predicate returns {@code true} will
-     * be included in the result.
+     * Filter this iterator using a predicate. Only items for which the predicate returns {@code true} will be included in the result.
+     *
      * @param predicate The predicate to filter the items with.
      * @return An iterator filtered by the predicate.
      */
     public ExtendedIterator<T> filter(final Predicate<T> predicate) {
-        return new ExtendedIterator<T>(new FilterIterator<>(this, predicate::test), this.throwOnRemove);
+        return new ExtendedIterator<>(new FilterIterator<>(this, predicate::test), this.throwOnRemove);
+    }
+
+    @Override
+    public void forEachRemaining(final Consumer<? super T> action) {
+        base.forEachRemaining(action);
+    }
+
+    @Override
+    public boolean hasNext() {
+        return base.hasNext();
     }
 
     /**
      * Map the elements of the iterator to a now type.
+     *
      * @param function The function to map elements of {@code <T>} to type {@code <U>}.
      * @return An Extended iterator that returns a {@code <U>} for very {@code <T>} in the original iterator.
      * @param <U> The object type to return.
      */
     public <U> ExtendedIterator<U> map(final Function<T, U> function) {
-        return new ExtendedIterator<U>(new TransformIterator<>(this, function::apply), false);
+        return new ExtendedIterator<>(new TransformIterator<>(this, function::apply), false);
     }
 
-    /**
-     * A method to add the remaining elements in the iterator an arbitrary collection.
-     * This method consumes the iterator.
-     * @param collection THe collection to add elements to.
-     * @return the {@code collection} with the elements added.
-     * @param <U> A collection of objects of type {@code <T>}.
-     */
-    public <U extends Collection<T>> U addTo(final U collection) {
-        this.forEachRemaining(collection::add);
-        return collection;
+    @Override
+    public T next() {
+        return base.next();
+    }
+
+    @Override
+    public void remove() {
+        if (throwOnRemove) {
+            throw new UnsupportedOperationException();
+        }
+        base.remove();
     }
 }
diff --git a/src/main/java/org/apache/commons/collections4/iterators/FilterIterator.java b/src/main/java/org/apache/commons/collections4/iterators/FilterIterator.java
index e9872a2b1..9fc280cd2 100644
--- a/src/main/java/org/apache/commons/collections4/iterators/FilterIterator.java
+++ b/src/main/java/org/apache/commons/collections4/iterators/FilterIterator.java
@@ -32,7 +32,7 @@ import org.apache.commons.collections4.functors.TruePredicate;
  * @param <E> the type of elements returned by this iterator.
  * @since 1.0
  */
-public class FilterIterator<E> implements Iterator<E> {
+public class FilterIterator<E> implements IteratorOperations<E> {
 
     /** The iterator to be filtered. */
     private Iterator<? extends E> iterator;
@@ -141,18 +141,6 @@ public class FilterIterator<E> implements Iterator<E> {
         iterator.remove();
     }
 
-    /**
-     * Returns the next item and removes it from the iterator.
-     *
-     * @return the next item from the iterator.
-     * @since 4.5.0-M3
-     */
-    public E removeNext() {
-        final E result = next();
-        remove();
-        return result;
-    }
-
     private Predicate<? super E> safePredicate(final Predicate<? super E> predicate) {
         return predicate != null ? predicate : TruePredicate.truePredicate();
     }
diff --git a/src/main/java/org/apache/commons/collections4/iterators/IteratorOperations.java b/src/main/java/org/apache/commons/collections4/iterators/IteratorOperations.java
new file mode 100644
index 000000000..54056e2cb
--- /dev/null
+++ b/src/main/java/org/apache/commons/collections4/iterators/IteratorOperations.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections4.iterators;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * Extends {@link Iterator} with additional default methods.
+ *
+ * @param <E> the type of elements returned by this iterator.
+ * @since 4.5.0-M3
+ */
+public interface IteratorOperations<E> extends Iterator<E> {
+
+    /**
+     * Adds the remaining elements in the iterator to an arbitrary {@link Collection}. This method consumes the iterator.
+     *
+     * @param collection The target collection to add elements to.
+     * @return the given {@code collection}.
+     * @param <C> A collection of objects of type {@code <E>}.
+     */
+    default <C extends Collection<E>> C addTo(final C collection) {
+        forEachRemaining(collection::add);
+        return collection;
+    }
+
+    /**
+     * Returns the next item and removes it from the iterator.
+     *
+     * @return the next item from the iterator.
+     */
+    default E removeNext() {
+        final E result = next();
+        remove();
+        return result;
+    }
+
+    /**
+     * Adds the remaining elements in the iterator to a new {@link Collection} provided by the supplier. This method consumes the iterator.
+     *
+     * @param collectionSupplier supplies a collection target.
+     * @param <C> the collection type.
+     * @return a new Collection containing the remaining elements of this instance.
+     */
+    default <C extends Collection<E>> C toCollection(final Supplier<C> collectionSupplier) {
+        return addTo(collectionSupplier.get());
+    }
+
+    /**
+     * Adds the remaining elements in the iterator to a new {@link List}. This method consumes the iterator.
+     *
+     * @return a new List containing the remaining elements of this instance.
+     */
+    default List<E> toList() {
+        return toCollection(ArrayList::new);
+    }
+
+    /**
+     * Adds the remaining elements in the iterator to a new {@link Set}. This method consumes the iterator.
+     *
+     * @return a new Set containing the remaining elements of this instance.
+     */
+    default Set<E> toSet() {
+        return toCollection(HashSet::new);
+    }
+
+}
diff --git a/src/test/java/org/apache/commons/collections4/iterators/FilterIteratorTest.java b/src/test/java/org/apache/commons/collections4/iterators/FilterIteratorTest.java
index 582e79a4d..ed28a538e 100644
--- a/src/test/java/org/apache/commons/collections4/iterators/FilterIteratorTest.java
+++ b/src/test/java/org/apache/commons/collections4/iterators/FilterIteratorTest.java
@@ -16,17 +16,22 @@
  */
 package org.apache.commons.collections4.iterators;
 
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Set;
 
 import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.collections4.Predicate;
@@ -125,6 +130,38 @@ public class FilterIteratorTest<E> extends AbstractIteratorTest<E> {
         iterator = null;
     }
 
+    @Test
+    public void testAddTo() {
+        final List<E> expected = new ArrayList<>(list);
+        expected.addAll(list);
+        final FilterIterator<E> filterIterator = new FilterIterator<>(list.iterator());
+        final List<E> actual = filterIterator.addTo(new ArrayList<>(list));
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testAddToCollection() {
+        final List<E> expected = new ArrayList<>(list);
+        expected.addAll(list);
+        final FilterIterator<E> filterIterator = new FilterIterator<>(list.iterator());
+        final List<E> actual = filterIterator.toCollection(() -> new ArrayList<>(list));
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testAddToEmpty() {
+        final FilterIterator<E> filterIterator = makeEmptyIterator();
+        final List<E> actual = filterIterator.addTo(new ArrayList<>(list));
+        assertEquals(list, actual);
+    }
+
+    @Test
+    public void testAddToEmptyToEmpty() {
+        final FilterIterator<E> filterIterator = makeEmptyIterator();
+        final List<E> actual = filterIterator.addTo(new ArrayList<>());
+        assertTrue(actual.isEmpty());
+    }
+
     /**
      * Tests a predicate that accepts some but not all elements.
      */
@@ -254,6 +291,30 @@ public class FilterIteratorTest<E> extends AbstractIteratorTest<E> {
         assertFalse(filterIterator.hasNext());
     }
 
+    @Test
+    public void testToCollectionAsDeque() {
+        final Deque<E> expected = new ArrayDeque<>(list);
+        final FilterIterator<E> filterIterator = new FilterIterator<>(list.iterator());
+        final Deque<E> actual = filterIterator.toCollection(ArrayDeque::new);
+        assertArrayEquals(expected.toArray(), actual.toArray());
+    }
+
+    @Test
+    public void testToList() {
+        final List<E> expected = new ArrayList<>(list);
+        final FilterIterator<E> filterIterator = new FilterIterator<>(list.iterator());
+        final List<E> actual = filterIterator.toList();
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testToSet() {
+        final Set<E> expected = new HashSet<>(list);
+        final FilterIterator<E> filterIterator = new FilterIterator<>(list.iterator());
+        final Set<E> actual = filterIterator.toSet();
+        assertEquals(expected, actual);
+    }
+
     private void verifyElementsInPredicate(final String[] elements) {
         final Predicate<E> pred = x -> {
             for (final String element : elements) {


(commons-collections) 01/02: Use final

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit c4a0d4c27eef624ab6edfeb7e8f2e672644d2c5e
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Fri Nov 1 17:37:09 2024 -0400

    Use final
    
    Sort members
---
 .../iterators/ExtendedIteratorTest.java            | 118 ++++++++++-----------
 1 file changed, 59 insertions(+), 59 deletions(-)

diff --git a/src/test/java/org/apache/commons/collections4/iterators/ExtendedIteratorTest.java b/src/test/java/org/apache/commons/collections4/iterators/ExtendedIteratorTest.java
index 936290511..f780822af 100644
--- a/src/test/java/org/apache/commons/collections4/iterators/ExtendedIteratorTest.java
+++ b/src/test/java/org/apache/commons/collections4/iterators/ExtendedIteratorTest.java
@@ -49,102 +49,102 @@ public class ExtendedIteratorTest {
     }
 
     @Test
-    public void testCreateNoRemove() {
-        Iterator<Integer> iter = ExtendedIterator.createNoRemove(collectionA.iterator());
-        assertThrows(UnsupportedOperationException.class, iter::remove);
+    public void testAddTo() {
+        final List<Integer> expected = new ArrayList<>(collectionA);
+        expected.addAll(collectionA);
+        final List<Integer> actual = ExtendedIterator.create(collectionA.iterator()).addTo(new ArrayList<>(collectionA));
+        assertEquals(expected, actual);
     }
 
     @Test
-    public void testCreateWithStream() {
-        Iterator<Integer> iter = ExtendedIterator.create(collectionA.stream());
-        assertThrows(UnsupportedOperationException.class, iter::remove);
-        List<Integer> actual = new ArrayList<>();
-        iter.forEachRemaining(actual::add);
+    public void testAndThen() {
+        final Iterator<Integer> iter1 = Arrays.asList(1, 2, 3).iterator();
+        final Iterator<Integer> iter2 = Arrays.asList(4, 5, 6).iterator();
+
+        final ExtendedIterator<Integer> underTest = ExtendedIterator.create(iter1).andThen(iter2);
+        final List<Integer> actual = new ArrayList<>();
+        underTest.forEachRemaining(actual::add);
         assertEquals(collectionA, actual);
     }
 
     @Test
-    public void testFlatten() {
-        Iterator<Iterator<Integer>> iteratorIterator = Arrays.asList(
-                Arrays.asList(1, 2, 3).iterator(),
-                Arrays.asList(4, 5, 6).iterator()
-        ).iterator();
-        Iterator<Integer>  iter = ExtendedIterator.flatten(iteratorIterator);
-        List<Integer> actual = new ArrayList<>();
+    public void testCreate() {
+        final Iterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
+        final List<Integer> actual = new ArrayList<>();
         iter.forEachRemaining(actual::add);
         assertEquals(collectionA, actual);
     }
 
     @Test
-    public void testEmptyIterator() {
-        assertFalse(ExtendedIterator.emptyIterator().hasNext());
+    public void testCreateNoRemove() {
+        final Iterator<Integer> iter = ExtendedIterator.createNoRemove(collectionA.iterator());
+        assertThrows(UnsupportedOperationException.class, iter::remove);
     }
 
     @Test
-    public void testCreate() {
-        Iterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
-        List<Integer> actual = new ArrayList<>();
+    public void testCreateWithStream() {
+        final Iterator<Integer> iter = ExtendedIterator.create(collectionA.stream());
+        assertThrows(UnsupportedOperationException.class, iter::remove);
+        final List<Integer> actual = new ArrayList<>();
         iter.forEachRemaining(actual::add);
         assertEquals(collectionA, actual);
     }
 
     @Test
-    public void testRemove() {
-        Iterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
-        Integer i = iter.next();
-        iter.remove();
-        assertFalse(collectionA.contains(i));
-        List<Integer> actual = new ArrayList<>();
-        iter.forEachRemaining(actual::add);
-        assertEquals(collectionA, actual);
+    public void testEmptyIterator() {
+        assertFalse(ExtendedIterator.emptyIterator().hasNext());
     }
 
     @Test
-    public void testRemoveNext() {
-        ExtendedIterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
-        Integer i = iter.removeNext();
-        assertFalse(collectionA.contains(i));
-        List<Integer> actual = new ArrayList<>();
-        iter.forEachRemaining(actual::add);
-        assertEquals(collectionA, actual);
+    public void testFilter() {
+        final List<Integer> expected = Arrays.asList(2, 4, 6);
+        final Predicate<Integer> predicate = i -> i % 2 == 0;
+        final ExtendedIterator<Integer> underTest = ExtendedIterator.create(collectionA.iterator()).filter(predicate);
+        final List<Integer> actual = new ArrayList<>();
+        underTest.forEachRemaining(actual::add);
+        assertEquals(expected, actual);
     }
 
     @Test
-    public void testAndThen() {
-        Iterator<Integer> iter1 = Arrays.asList(1, 2, 3).iterator();
-        Iterator<Integer> iter2 = Arrays.asList(4, 5, 6).iterator();
-
-        ExtendedIterator<Integer> underTest = ExtendedIterator.create(iter1).andThen(iter2);
-        List<Integer> actual = new ArrayList<>();
-        underTest.forEachRemaining(actual::add);
+    public void testFlatten() {
+        final Iterator<Iterator<Integer>> iteratorIterator = Arrays.asList(
+                Arrays.asList(1, 2, 3).iterator(),
+                Arrays.asList(4, 5, 6).iterator()
+        ).iterator();
+        final Iterator<Integer>  iter = ExtendedIterator.flatten(iteratorIterator);
+        final List<Integer> actual = new ArrayList<>();
+        iter.forEachRemaining(actual::add);
         assertEquals(collectionA, actual);
     }
 
     @Test
-    public void testFilter() {
-        List<Integer> expected = Arrays.asList(2, 4, 6);
-        Predicate<Integer> predicate = i -> i % 2 == 0;
-        ExtendedIterator<Integer> underTest = ExtendedIterator.create(collectionA.iterator()).filter(predicate);
-        List<Integer> actual = new ArrayList<>();
+    public void testMap() {
+        final List<Double> expected = Arrays.asList(0.5, 1., 1.5, 2.0, 2.5, 3.0);
+        final Function<Integer, Double> function = i -> i / 2.0;
+        final ExtendedIterator<Double> underTest = ExtendedIterator.create(collectionA.iterator()).map(function);
+        final List<Double> actual = new ArrayList<>();
         underTest.forEachRemaining(actual::add);
         assertEquals(expected, actual);
     }
 
     @Test
-    public void testMap() {
-        List<Double> expected = Arrays.asList(0.5, 1., 1.5, 2.0, 2.5, 3.0);
-        Function<Integer, Double> function = i -> i / 2.0;
-        ExtendedIterator<Double> underTest = ExtendedIterator.create(collectionA.iterator()).map(function);
-        List<Double> actual = new ArrayList<>();
-        underTest.forEachRemaining(actual::add);
-        assertEquals(expected, actual);
+    public void testRemove() {
+        final Iterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
+        final Integer i = iter.next();
+        iter.remove();
+        assertFalse(collectionA.contains(i));
+        final List<Integer> actual = new ArrayList<>();
+        iter.forEachRemaining(actual::add);
+        assertEquals(collectionA, actual);
     }
 
     @Test
-    public void testAddTo() {
-        List<Integer> expected = new ArrayList<>(collectionA);
-        expected.addAll(collectionA);
-        List<Integer> actual = ExtendedIterator.create(collectionA.iterator()).addTo(new ArrayList<>(collectionA));
-        assertEquals(expected, actual);
+    public void testRemoveNext() {
+        final ExtendedIterator<Integer> iter = ExtendedIterator.create(collectionA.iterator());
+        final Integer i = iter.removeNext();
+        assertFalse(collectionA.contains(i));
+        final List<Integer> actual = new ArrayList<>();
+        iter.forEachRemaining(actual::add);
+        assertEquals(collectionA, actual);
     }
 }