This is an automated email from the ASF dual-hosted git repository.
daim pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new 7bda86b8dc OAK-11674 : added Iterators.filter replacement in
oak-commons (#2245)
7bda86b8dc is described below
commit 7bda86b8dc417ea6631759b901d904e34df281a7
Author: Rishabh Kumar <[email protected]>
AuthorDate: Thu Apr 24 15:58:14 2025 +0530
OAK-11674 : added Iterators.filter replacement in oak-commons (#2245)
Co-authored-by: Rishabh Kumar <[email protected]>
---
.../oak/commons/collections/IteratorUtils.java | 30 ++++++
.../oak/commons/collections/IteratorUtilsTest.java | 114 +++++++++++++++++++++
2 files changed, 144 insertions(+)
diff --git
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
index b48e109a61..6d7d62fccf 100644
---
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
+++
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
@@ -30,6 +30,7 @@ import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
+import java.util.function.Predicate;
/**
* Utility methods for {@link Iterator} conversions.
@@ -369,4 +370,33 @@ public class IteratorUtils {
iterators.forEachRemaining(eIteratorChain::addIterator);
return eIteratorChain;
}
+
+ /**
+ * Returns an iterator containing only the elements that match the given
predicate.
+ * <p>
+ * This method creates a new iterator that will iterate through elements
from the
+ * source iterator but only return elements that satisfy the specified
predicate.
+ * The filtering occurs during iteration and the method doesn't consume
the source iterator
+ * until the returned iterator is advanced.
+ * <p>
+ * Example usage:
+ * <pre>
+ * Iterator<Integer> numbers = Arrays.asList(1, 2, 3, 4,
5).iterator();
+ * Predicate<Integer> isEven = n -> n % 2 == 0;
+ * Iterator<Integer> evenNumbers = IteratorUtils.filter(numbers,
isEven);
+ * // evenNumbers will iterate through 2, 4
+ * </pre>
+ * <p>
+ * The returned iterator supports {@link Iterator#remove()} if the source
iterator supports it.
+ *
+ * @param <T> the type of objects in the iterator
+ * @param itr the source iterator, must not be null
+ * @param predicate the predicate to apply to each element, must not be
null
+ * @return a filtered iterator
+ * @throws NullPointerException if either the iterator or predicate is null
+ */
+ public static <T> Iterator<T> filter(final Iterator<? extends T> itr,
final Predicate<? super T> predicate) {
+ return
org.apache.commons.collections4.IteratorUtils.filteredIterator(itr,
predicate::test);
+ }
}
+
diff --git
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
index 47a4393823..faa04276ec 100644
---
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
+++
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
@@ -817,4 +817,118 @@ public class IteratorUtilsTest {
Assert.assertThrows(NullPointerException.class, () ->
IteratorUtils.chainedIterator(new ArrayList<>(Arrays.asList(iterator1,
iterator2, null)).iterator()));
}
+
+ @Test
+ public void testFilterWithMatchingElements() {
+ List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
+ Iterator<Integer> filtered = IteratorUtils.filter(list.iterator(), n
-> n % 2 == 0);
+
+ List<Integer> result = new ArrayList<>();
+ filtered.forEachRemaining(result::add);
+
+ Assert.assertEquals(Arrays.asList(2, 4), result);
+ }
+
+ @Test
+ public void testFilterWithNoMatchingElements() {
+ List<String> list = Arrays.asList("apple", "banana", "cherry");
+ Iterator<String> filtered = IteratorUtils.filter(list.iterator(), s ->
s.startsWith("d"));
+
+ Assert.assertFalse(filtered.hasNext());
+ }
+
+ @Test
+ public void testFilterWithAllMatchingElements() {
+ List<Integer> list = Arrays.asList(10, 20, 30, 40);
+ Iterator<Integer> filtered = IteratorUtils.filter(list.iterator(), n
-> n > 0);
+
+ List<Integer> result = new ArrayList<>();
+ filtered.forEachRemaining(result::add);
+
+ Assert.assertEquals(list, result);
+ }
+
+ @Test
+ public void testFilterWithEmptyIterator() {
+ Iterator<String> emptyIterator = Collections.emptyIterator();
+ Iterator<String> filtered = IteratorUtils.filter(emptyIterator, s ->
true);
+
+ Assert.assertFalse(filtered.hasNext());
+ }
+
+ @Test
+ public void testFilterWithNullIterator() {
+ Assert.assertThrows(NullPointerException.class, () ->
IteratorUtils.filter(null, item -> true));
+ }
+
+ @Test
+ public void testFilterWithNullPredicate() {
+ Iterator<String> iterator = Arrays.asList("a", "b").iterator();
+ Assert.assertThrows(NullPointerException.class, () ->
IteratorUtils.filter(iterator, null));
+ }
+
+ @Test
+ public void testFilterWithRemove() {
+ List<String> list = new ArrayList<>(Arrays.asList("keep", "remove",
"keep"));
+ Iterator<String> filtered = IteratorUtils.filter(list.iterator(),
"keep"::equals);
+
+ // First element matches
+ Assert.assertTrue(filtered.hasNext());
+ Assert.assertEquals("keep", filtered.next());
+ filtered.remove();
+
+ // Skip "remove" as it doesn't match
+ Assert.assertTrue(filtered.hasNext());
+ Assert.assertEquals("keep", filtered.next());
+
+ Assert.assertEquals(Arrays.asList("remove", "keep"), list);
+ }
+
+ @Test
+ public void testFilterWithNullElements() {
+ List<String> list = Arrays.asList("a", null, "b", null, "c");
+ Iterator<String> filtered = IteratorUtils.filter(list.iterator(),
Objects::isNull);
+
+ List<String> result = new ArrayList<>();
+ filtered.forEachRemaining(result::add);
+
+ Assert.assertEquals(Arrays.asList(null, null), result);
+ }
+
+ @Test
+ public void testFilterWithCustomObjects() {
+ class Person {
+ private final String name;
+ private final int age;
+
+ Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ List<Person> people = Arrays.asList(
+ new Person("Alice", 25),
+ new Person("Bob", 17),
+ new Person("Charlie", 30),
+ new Person("David", 16)
+ );
+
+ // Filter adults (age >= 18)
+ Iterator<Person> adults = IteratorUtils.filter(people.iterator(), p ->
p.getAge() >= 18);
+
+ List<String> adultNames = new ArrayList<>();
+ adults.forEachRemaining(p -> adultNames.add(p.toString()));
+
+ Assert.assertEquals(Arrays.asList("Alice", "Charlie"), adultNames);
+ }
}