diff --git a/src/main/java/org/apache/commons/collections4/IterableUtils.java b/src/main/java/org/apache/commons/collections4/IterableUtils.java
index 38a1c11a51..e6c52fcb16 100644
--- a/src/main/java/org/apache/commons/collections4/IterableUtils.java
+++ b/src/main/java/org/apache/commons/collections4/IterableUtils.java
@@ -26,6 +26,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Supplier;
import org.apache.commons.collections4.functors.EqualPredicate;
import org.apache.commons.collections4.iterators.LazyIteratorChain;
@@ -140,6 +141,39 @@ protected Iterator extends E> nextIterator(final int count) {
};
}
+ /**
+ * Combines the provided iterables into a single iterable.
+ *
+ * The returned iterable has an iterator that traverses the elements in the order
+ * of the arguments, i.e. iterables[0], iterables[1], .... The source iterators
+ * are not polled until necessary.
+ *
+ * The returned iterable's iterator supports {@code remove()} when the corresponding
+ * input iterator supports it.
+ *
+ * @param the element type
+ * @param iterableSuppliers the iterables to combine, may not be null
+ * @return a new iterable, combining the provided iterables
+ * @throws NullPointerException if either of the provided iterables is null
+ */
+ public static Iterable chainedIterable(final Supplier>... iterableSuppliers) {
+ checkNotNull(iterableSuppliers);
+ return new FluentIterable() {
+ @Override
+ public Iterator iterator() {
+ return new LazyIteratorChain() {
+ @Override
+ protected Iterator extends E> nextIterator(final int count) {
+ if (count > iterableSuppliers.length) {
+ return null;
+ }
+ return iterableSuppliers[count - 1].get().iterator();
+ }
+ };
+ }
+ };
+ }
+
/**
* Combines two iterables into a single iterable.
*
@@ -231,6 +265,19 @@ static void checkNotNull(final Iterable>... iterables) {
}
}
+ /**
+ * Fail-fast check for null arguments.
+ *
+ * @param suppliers the suppliers to check
+ * @throws NullPointerException if the argument or any of its contents is null
+ */
+ static void checkNotNull(final Supplier>... suppliers) {
+ Objects.requireNonNull(suppliers, "suppliers");
+ for (final Supplier> supplier : suppliers) {
+ Objects.requireNonNull(supplier, "supplier");
+ }
+ }
+
/**
* Combines the two provided iterables into an ordered iterable using the
* provided comparator. If the comparator is null, natural ordering will be
@@ -384,7 +431,7 @@ public static Set duplicateSet(final Iterable iterable) {
}
/**
- * Worker method for {@link #duplicateSet(Collection)} and friends.
+ * Worker method for {@link #duplicateSet(Iterable)} and friends.
*
* @param the type of Collection.
* @param the type of elements in the Collection.
diff --git a/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java b/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java
index ab8995b91f..a48b05205f 100644
--- a/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java
+++ b/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java
@@ -33,14 +33,21 @@
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.functors.EqualPredicate;
import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -653,4 +660,105 @@ public void testToStringWithNullArguments() {
}, StringUtils.EMPTY, "(", null), "expecting NullPointerException"));
}
+ static final class MockMongoAlertQueryService {
+
+ public Iterable