iterator) {
+ return iterator == null ? Stream.empty() : StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
+ }
+
/**
* Gets an array based on an iterator.
*
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 The type of object returned from the iterator.
* @since 4.5.0-M3
*/
-public final class ExtendedIterator implements Iterator {
- /**
- * Set to true
if this wrapping doesn't permit the use of
- * {@link #remove()}, otherwise removal is delegated to the base iterator.
- */
- private final boolean throwOnRemove;
+public final class ExtendedIterator implements IteratorOperations {
/**
- * Creates an ExtendedIterator wrapped round it
,
- * which does not permit .remove()
- * even if it
does.
+ * Create an ExtendedIterator returning the elements of it
. If it
is itself an ExtendedIterator, return that; otherwise wrap
+ * it
.
+ *
+ * @param The type of object returned from the iterator.
+ * @param it The iterator to wrap.
+ * @return An Extended iterator wrapping {@code it}
+ */
+ public static ExtendedIterator create(final Iterator it) {
+ return it instanceof ExtendedIterator> ? (ExtendedIterator) it : new ExtendedIterator<>(it, false);
+ }
+
+ /**
+ * Creates an ExtendedIterator wrapped round a {@link Stream}. The extended iterator does not permit .remove()
.
+ *
+ * The stream should not be used directly. The effect of doing so is undefined.
+ *
+ *
+ * @param 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 ExtendedIterator create(final Stream stream) {
+ return new ExtendedIterator<>(stream.iterator(), true);
+ }
+
+ /**
+ * Creates an ExtendedIterator wrapped round it
, which does not permit .remove()
even if it
does.
+ *
+ * @param 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 implements Iterator {
}
/**
- * Creates an ExtendedIterator wrapped round a {@link Stream}.
- * The extended iterator does not permit .remove()
.
- *
- * The stream should not be used directly. The effect of doing so is
- * undefined.
- *
- * @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 ExtendedIterator create(final Stream stream) {
- return new ExtendedIterator(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 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 implements Iterator {
}
/**
- * Creates an empty Extended iterator.
- * @return An empty Extended iterator.
+ * Set to true
if this wrapping doesn't permit the use of {@link #remove()}, otherwise removal is delegated to the base iterator.
*/
- public static ExtendedIterator> emptyIterator() {
- return new ExtendedIterator<>(Collections.emptyIterator(), false);
- }
+ private final boolean throwOnRemove;
- /**
- * Create an ExtendedIterator returning the elements of it
.
- * If it
is itself an ExtendedIterator, return that;
- * otherwise wrap it
.
- * @param it The iterator to wrap.
- * @return An Extended iterator wrapping {@code it}
- */
- public static ExtendedIterator create(final Iterator it) {
- return it instanceof ExtendedIterator>
- ? (ExtendedIterator) it
- : new ExtendedIterator<>(it, false);
- }
-
- /** 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 implements Iterator {
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 The type of object returned from the other iterator.
@@ -159,38 +128,50 @@ public final class ExtendedIterator implements Iterator {
((IteratorChain) base).addIterator(other);
return this;
}
- return new ExtendedIterator(new IteratorChain(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 filter(final Predicate predicate) {
- return new ExtendedIterator(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 } to type {@code }.
* @return An Extended iterator that returns a {@code } for very {@code } in the original iterator.
* @param The object type to return.
*/
public ExtendedIterator map(final Function function) {
- return new ExtendedIterator(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 A collection of objects of type {@code }.
- */
- public > 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 the type of elements returned by this iterator.
* @since 1.0
*/
-public class FilterIterator implements Iterator {
+public class FilterIterator implements IteratorOperations {
/** The iterator to be filtered. */
private Iterator extends E> iterator;
@@ -141,18 +141,6 @@ public class FilterIterator implements Iterator {
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 the type of elements returned by this iterator.
+ * @since 4.5.0-M3
+ */
+public interface IteratorOperations extends Iterator {
+
+ /**
+ * 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 A collection of objects of type {@code }.
+ */
+ default > 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 the collection type.
+ * @return a new Collection containing the remaining elements of this instance.
+ */
+ default > C toCollection(final Supplier 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 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 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 extends AbstractIteratorTest {
iterator = null;
}
+ @Test
+ public void testAddTo() {
+ final List expected = new ArrayList<>(list);
+ expected.addAll(list);
+ final FilterIterator filterIterator = new FilterIterator<>(list.iterator());
+ final List actual = filterIterator.addTo(new ArrayList<>(list));
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testAddToCollection() {
+ final List expected = new ArrayList<>(list);
+ expected.addAll(list);
+ final FilterIterator filterIterator = new FilterIterator<>(list.iterator());
+ final List actual = filterIterator.toCollection(() -> new ArrayList<>(list));
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testAddToEmpty() {
+ final FilterIterator filterIterator = makeEmptyIterator();
+ final List actual = filterIterator.addTo(new ArrayList<>(list));
+ assertEquals(list, actual);
+ }
+
+ @Test
+ public void testAddToEmptyToEmpty() {
+ final FilterIterator filterIterator = makeEmptyIterator();
+ final List 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 extends AbstractIteratorTest {
assertFalse(filterIterator.hasNext());
}
+ @Test
+ public void testToCollectionAsDeque() {
+ final Deque expected = new ArrayDeque<>(list);
+ final FilterIterator filterIterator = new FilterIterator<>(list.iterator());
+ final Deque actual = filterIterator.toCollection(ArrayDeque::new);
+ assertArrayEquals(expected.toArray(), actual.toArray());
+ }
+
+ @Test
+ public void testToList() {
+ final List expected = new ArrayList<>(list);
+ final FilterIterator filterIterator = new FilterIterator<>(list.iterator());
+ final List actual = filterIterator.toList();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testToSet() {
+ final Set expected = new HashSet<>(list);
+ final FilterIterator filterIterator = new FilterIterator<>(list.iterator());
+ final Set actual = filterIterator.toSet();
+ assertEquals(expected, actual);
+ }
+
private void verifyElementsInPredicate(final String[] elements) {
final Predicate pred = x -> {
for (final String element : elements) {