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 df073f36bf OAK-11706 : added Iterators.limit replacement in oak-commons (#2281) df073f36bf is described below commit df073f36bfd5e904eb9879ca68468c17f2ae88ca Author: Rishabh Kumar <rishabhdaim1...@gmail.com> AuthorDate: Thu May 8 16:54:21 2025 +0530 OAK-11706 : added Iterators.limit replacement in oak-commons (#2281) Co-authored-by: Rishabh Kumar <d...@adobe.com> --- .../oak/commons/collections/IteratorUtils.java | 27 +++++++ .../oak/commons/collections/IteratorUtilsTest.java | 91 ++++++++++++++++++++++ 2 files changed, 118 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 7d98918b8c..5c01691d71 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 @@ -531,5 +531,32 @@ public class IteratorUtils { } }); } + + /** + * Returns an iterator that will only provide at most the first N elements from given iterator. + * <p> + * This method returns an iterator that will stop after returning the + * specified number of elements or when the source iterator is exhausted, + * whichever comes first. + * <p> + * Example usage: + * <pre> + * Iterator<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David").iterator(); + * Iterator<String> firstTwo = IteratorUtils.limit(names, 2); + * // firstTwo will iterate through "Alice", "Bob" only + * </pre> + * + * @param <T> the type of elements in the iterator + * @param iterator the source iterator to limit, must not be null + * @param limit the maximum number of elements to return, must not be negative + * @return an iterator limited to the specified number of elements + * @throws NullPointerException if the iterator is null + * @throws IllegalArgumentException if limit is negative + */ + public static <T> Iterator<T> limit(final Iterator<T> iterator, final int limit) { + Objects.requireNonNull(iterator); + Validate.checkArgument(limit >= 0, "limit is negative"); + return org.apache.commons.collections4.IteratorUtils.boundedIterator(iterator, limit); + } } 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 7abc2a8186..d2db77d784 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 @@ -1246,4 +1246,95 @@ public class IteratorUtilsTest { // But original list should still have all elements Assert.assertEquals(Arrays.asList("a", "b", "c", "d"), list); } + + @Test + public void testLimitWithSmallerLimit() { + List<String> list = Arrays.asList("a", "b", "c", "d"); + Iterator<String> limited = IteratorUtils.limit(list.iterator(), 2); + + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("a", limited.next()); + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("b", limited.next()); + Assert.assertFalse(limited.hasNext()); + } + + @Test + public void testLimitWithLargerLimit() { + List<String> list = Arrays.asList("a", "b", "c"); + Iterator<String> limited = IteratorUtils.limit(list.iterator(), 5); + + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("a", limited.next()); + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("b", limited.next()); + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("c", limited.next()); + Assert.assertFalse(limited.hasNext()); + } + + @Test + public void testLimitWithEqualLimit() { + List<String> list = Arrays.asList("a", "b", "c"); + Iterator<String> limited = IteratorUtils.limit(list.iterator(), 3); + + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("a", limited.next()); + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("b", limited.next()); + Assert.assertTrue(limited.hasNext()); + Assert.assertEquals("c", limited.next()); + Assert.assertFalse(limited.hasNext()); + } + + @Test + public void testLimitWithZeroLimit() { + List<String> list = Arrays.asList("a", "b", "c"); + Iterator<String> limited = IteratorUtils.limit(list.iterator(), 0); + + Assert.assertFalse(limited.hasNext()); + } + + @Test + public void testLimitWithEmptyIterator() { + Iterator<String> limited = IteratorUtils.limit(Collections.emptyIterator(), 5); + Assert.assertFalse(limited.hasNext()); + } + + @Test + public void testLimitWithNullIterator() { + Assert.assertThrows(NullPointerException.class, () -> IteratorUtils.limit(null, 5)); + } + + @Test + public void testLimitWithNegativeLimit() { + final List<String> list = List.of("a", "b", "c"); + Assert.assertThrows(IllegalArgumentException.class, () -> IteratorUtils.limit(list.iterator(), -1)); + } + + @Test + public void testLimitWithRemove() { + List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c")); + Iterator<String> limited = IteratorUtils.limit(list.iterator(), 2); + + Assert.assertEquals("a", limited.next()); + limited.remove(); // Remove "a" + Assert.assertEquals("b", limited.next()); + + Assert.assertEquals(List.of("b", "c"), list); + } + + @Test + public void testLimitChaining() { + List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); + Iterator<Integer> limited = IteratorUtils.limit(list.iterator(), 4); // First 4 elements + Iterator<Integer> furtherLimited = IteratorUtils.limit(limited, 2); // First 2 of those 4 + + List<Integer> result = new ArrayList<>(); + while (furtherLimited.hasNext()) { + result.add(furtherLimited.next()); + } + + Assert.assertEquals(List.of(1, 2), result); + } }