diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java index a92e775b69a..2fe4a502734 100644 --- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java @@ -21,6 +21,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -520,6 +521,52 @@ public static Stream toStream(@NotNull Iterator iterator) { return StreamSupport.stream(toIterable(iterator).spliterator(), false); } + /** + * Compares two iterables for element-wise equality. + * + * @param iterable1 the first iterable to compare, must not be {@code null} + * @param iterable2 the second iterable to compare, must not be {@code null} + * @return {@code true} if both iterables contain the same elements in the same order; {@code false} otherwise + * @throws NullPointerException if either iterable is {@code null} + */ + public static boolean elementsEqual(Iterable iterable1, Iterable iterable2) { + Objects.requireNonNull(iterable1); + Objects.requireNonNull(iterable2); + + if (iterable1 instanceof Collection && iterable2 instanceof Collection) { + Collection collection1 = (Collection) iterable1; + Collection collection2 = (Collection) iterable2; + if (collection1.size() != collection2.size()) { + return false; + } else { + return elementsEqual(iterable1.iterator(), iterable2.iterator()); + } + } + + return elementsEqual(iterable1.iterator(), iterable2.iterator()); + } + + /** + * Compares two iterators for element-wise equality. + * + * @param iterator1 the first iterator to compare, must not be {@code null} + * @param iterator2 the second iterator to compare, must not be {@code null} + * @return {@code true} if both iterators contain the same elements in the same order; {@code false} otherwise + * @throws NullPointerException if either iterator is {@code null} + */ + public static boolean elementsEqual(Iterator iterator1, Iterator iterator2) { + Objects.requireNonNull(iterator1); + Objects.requireNonNull(iterator2); + + while (iterator1.hasNext() && iterator2.hasNext()) { + if (!Objects.equals(iterator1.next(), iterator2.next())) { + return false; + } + } + + return !iterator1.hasNext() && !iterator2.hasNext(); + } + /** * Ensure the capacity of a map or set given the expected number of elements. * diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java index 15a5ca2ab0a..8e04d91d372 100644 --- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java @@ -38,6 +38,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class CollectionUtilsTest { @@ -725,4 +727,106 @@ public void ensureCapacityWithNegativeValue() { int capacity = CollectionUtils.ensureCapacity(-8); fail("Should throw IllegalArgumentException"); } + + @Test + public void testEqualsNonEmptyIterables() { + Iterable iterable1 = Arrays.asList(1, 2, 3); + Iterable iterable2 = Arrays.asList(1, 2, 3); + assertTrue(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testUnequalNonEmptyIterables() { + Iterable iterable1 = Arrays.asList(1, 2, 3); + Iterable iterable2 = Arrays.asList(1, 2, 4); + assertFalse(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualsEmptyIterables() { + Iterable iterable1 = Collections.emptyList(); + Iterable iterable2 = Collections.emptyList(); + assertTrue(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualsOneEmptyOneNonEmptyIterable() { + Iterable iterable1 = Collections.emptyList(); + Iterable iterable2 = Arrays.asList(1, 2, 3); + assertFalse(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualsDifferentTypeOfElements() { + Iterable iterable1 = Arrays.asList("apple", "banana", "cherry"); + Iterable iterable2 = Arrays.asList(1, 2, 3); + assertFalse(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualsNullValuesInIterables() { + Iterable iterable1 = Arrays.asList("apple", null, "cherry"); + Iterable iterable2 = Arrays.asList("apple", null, "cherry"); + assertTrue(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualsDifferentSizesIterables() { + Iterable iterable1 = Arrays.asList(1, 2); + Iterable iterable2 = Arrays.asList(1, 2, 3); + assertFalse(CollectionUtils.elementsEqual(iterable1, iterable2)); + } + + @Test + public void testEqualNonEmptyIterators() { + Iterator iterator1 = Arrays.asList(1, 2, 3).iterator(); + Iterator iterator2 = Arrays.asList(1, 2, 3).iterator(); + assertTrue(CollectionUtils.elementsEqual(iterator1, iterator2)); + } + + + @Test + public void testEqualNonEmptyIteratorsWithDifferentValues() { + Iterator iterator1 = Arrays.asList(1, 2, 3).iterator(); + Iterator iterator2 = Arrays.asList(1, 2, 4).iterator(); + assertFalse(CollectionUtils.elementsEqual(iterator1, iterator2)); + + } + + @Test + public void testEqualsEmptyIterators() { + Iterator iterator1 = Collections.emptyIterator(); + Iterator iterator2 = Collections.emptyIterator(); + assertTrue(CollectionUtils.elementsEqual(iterator1, iterator2)); + } + + @Test + public void testEqualsOneEmptyAndOneNonEmptyIterator() { + Iterator iterator1 = Collections.emptyIterator(); + Iterator iterator2 = Arrays.asList(1, 2, 3).iterator(); + assertFalse(CollectionUtils.elementsEqual(iterator1, iterator2)); + + } + + @Test + public void testEqualsDifferentTypesElementsInIterators() { + Iterator iterator1 = Arrays.asList("apple", "banana").iterator(); + Iterator iterator2 = Arrays.asList(1, 2).iterator(); + assertFalse(CollectionUtils.elementsEqual(iterator1, iterator2)); + + } + + @Test + public void testEqualsNullValuesInIterators() { + Iterator iterator1 = Arrays.asList("apple", null).iterator(); + Iterator iterator2 = Arrays.asList("apple", null).iterator(); + assertTrue(CollectionUtils.elementsEqual(iterator1, iterator2)); + } + + @Test + public void testEqualsDifferentSizesIterators() { + Iterator iterator1 = Arrays.asList(1, 2).iterator(); + Iterator iterator2 = Arrays.asList(1, 2, 3).iterator(); + assertFalse(CollectionUtils.elementsEqual(iterator1, iterator2)); + } } \ No newline at end of file