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 a2595d9cb9 OAK-11575 : added util to replace Iterables.getLast in 
oak-commons (#2162)
a2595d9cb9 is described below

commit a2595d9cb99fceb1643b4c6214ffef91cc176a96
Author: Rishabh Kumar <[email protected]>
AuthorDate: Tue Mar 11 13:21:43 2025 +0530

    OAK-11575 : added util to replace Iterables.getLast in oak-commons (#2162)
    
    * OAK-11575 : added util to replace Iterables.getLast in oak-commons
    
    * OAK-11575 : addressed review comments to update comments
    
    ---------
    
    Co-authored-by: Rishabh Kumar <[email protected]>
---
 .../oak/commons/collections/IterableUtils.java     | 28 +++++++++
 .../oak/commons/collections/IterableUtilsTest.java | 72 ++++++++++++++++++++++
 2 files changed, 100 insertions(+)

diff --git 
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IterableUtils.java
 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IterableUtils.java
index a09e096e60..9f7b8d393a 100644
--- 
a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IterableUtils.java
+++ 
b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IterableUtils.java
@@ -446,4 +446,32 @@ public class IterableUtils {
         Objects.requireNonNull(predicate, "Predicate must not be null.");
         return org.apache.commons.collections4.IterableUtils.find(iterable, 
predicate::test);
     }
+
+    /**
+     * Returns the last element of the specified iterable, or null if the 
iterable is empty.
+     * <p>
+     * The iterable must be fully traversed to find the last element.
+     *
+     * @param <T> the type of elements in the iterable
+     * @param iterable the iterable to get the last element from, must not be 
null
+     * @return the last element in the iterable or null if the iterable is 
empty
+     */
+    public static <T> T getLast(final Iterable<T> iterable) {
+
+        Objects.requireNonNull(iterable, "Iterable must not be null.");
+
+        // Optimize for Lists
+        if (iterable instanceof List) {
+            final List<T> list = (List<T>) iterable;
+            return list.isEmpty() ? null : list.get(list.size() - 1);
+        }
+
+        // For non-List iterables
+        T last = null;
+        for (final T element : iterable) {
+            last = element;
+        }
+
+        return last;
+    }
 }
diff --git 
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IterableUtilsTest.java
 
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IterableUtilsTest.java
index 7984918191..4acd80283c 100644
--- 
a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IterableUtilsTest.java
+++ 
b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IterableUtilsTest.java
@@ -26,9 +26,11 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -1030,4 +1032,74 @@ public class IterableUtilsTest {
         Integer result = IterableUtils.find(customIterable, i -> i % 10 == 0);
         Assert.assertEquals(Integer.valueOf(10), result);
     }
+
+    @Test
+    public void testGetLastWithNonEmptyIterable() {
+        List<String> list = Arrays.asList("a", "b", "c");
+        String result = IterableUtils.getLast(list);
+        Assert.assertEquals("c", result);
+    }
+
+    @Test
+    public void testGetLastWithEmptyIterable() {
+        List<String> list = Collections.emptyList();
+        String result = IterableUtils.getLast(list);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testGetLastWithNullIterable() {
+        Assert.assertThrows(NullPointerException.class, () -> 
IterableUtils.getLast(null));
+    }
+
+    @Test
+    public void testGetLastWithSingleElement() {
+        List<Integer> list = Collections.singletonList(42);
+        Integer result = IterableUtils.getLast(list);
+        Assert.assertEquals(Integer.valueOf(42), result);
+    }
+
+    @Test
+    public void testGetLastWithNullLastElement() {
+        List<String> list = Arrays.asList("a", "b", null);
+        String result = IterableUtils.getLast(list);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testGetLastWithCustomIterable() {
+        // Custom iterable that doesn't implement Collection
+        Iterable<Integer> customIterable = () -> Arrays.asList(5, 10, 
15).iterator();
+        Integer result = IterableUtils.getLast(customIterable);
+        Assert.assertEquals(Integer.valueOf(15), result);
+    }
+
+    @Test
+    public void testGetLastWithLargeIterable() {
+        List<Integer> list = new ArrayList<>();
+        for (int i = 0; i < 1000; i++) {
+            list.add(i);
+        }
+        Integer result = IterableUtils.getLast(list);
+        Assert.assertEquals(Integer.valueOf(999), result);
+    }
+
+    @Test
+    public void testGetLastWithListImplementation() {
+        // Test to confirm optimization for List works
+        List<String> list = Arrays.asList("a", "b", "c", "d");
+        String result = IterableUtils.getLast(list);
+        Assert.assertEquals("d", result);
+    }
+
+    @Test
+    public void testGetLastWithNonListCollection() {
+        // Test with a Collection that isn't a List
+        Set<String> set = new LinkedHashSet<>();
+        set.add("a");
+        set.add("b");
+        set.add("c");
+        String result = IterableUtils.getLast(set);
+        Assert.assertEquals("c", result);
+    }
 }

Reply via email to