This is an automated email from the ASF dual-hosted git repository.

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git


The following commit(s) were added to refs/heads/master by this push:
     new 572f9be73 Refactor summing sizes for duplication
572f9be73 is described below

commit 572f9be73d743cc3d360581f18680859c6a45b96
Author: Gary Gregory <[email protected]>
AuthorDate: Fri Jul 10 15:32:55 2026 -0400

    Refactor summing sizes for duplication
    
    - Fail faster
    - Add IterableUtils.sumSizesToInt(Iterable<? extends Collection<E>>)
---
 src/changes/changes.xml                            |  1 +
 .../apache/commons/collections4/IterableUtils.java | 39 ++++++++++++++++++++++
 .../collection/CompositeCollection.java            |  7 ++--
 .../multimap/AbstractMultiValuedMap.java           |  7 ++--
 .../collections4/multiset/AbstractMultiSet.java    | 16 +++++----
 .../commons/collections4/set/CompositeSet.java     |  7 ++--
 .../multimap/AbstractMultiValuedMapTest.java       |  1 +
 7 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d4ddb86b7..593148abe 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -85,6 +85,7 @@
     <action type="add" dev="ggregory" due-to="Gary Gregory">Add a Maven 
benchmark profile for JMH.</action>
     <action type="add" issue="COLLECTIONS-893" dev="paulk" due-to="Paul 
King">Add SortedMultiSet interface, TreeMultiSet implementation, sorted 
multiset decorators, and MultiSetUtils factory methods, giving MultiSet feature 
parity with SortedBag/TreeBag.</action>
     <action type="add" issue="COLLECTIONS-893" dev="paulk" due-to="Paul 
King">Add MultiSetUtils.containsOccurrences/removeOccurrences/retainOccurrences 
providing Bag's cardinality-respecting semantics under explicit names, and 
Bag-to-MultiSet migration notes in the Bag javadoc.</action>
+    <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
IterableUtils.sumSizes(Iterable&lt;? extends Collection&lt;E&gt;&gt;).</action>
     <!-- UPDATE -->
     <action type="update" dev="ggregory" due-to="Gary Gregory, 
Dependabot">Bump org.apache.commons:commons-parent from 81 to 102 #612, #645, 
#662, #663.</action>
     <action type="update" dev="ggregory" due-to="Gary Gregory">Bump 
com.google.guava:guava-testlib from 33.3.1-jre to 33.5.0-jre #644.</action>
diff --git a/src/main/java/org/apache/commons/collections4/IterableUtils.java 
b/src/main/java/org/apache/commons/collections4/IterableUtils.java
index 133b8a93e..4475ffff6 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.LinkedHashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.ToIntFunction;
 
 import org.apache.commons.collections4.functors.EqualPredicate;
 import org.apache.commons.collections4.functors.NullPredicate;
@@ -927,6 +928,44 @@ public class IterableUtils {
         };
     }
 
+    /**
+     * Returns the sum of the sizes of the collections in the given iterable.
+     * <p>
+     * Integer overflow is capped at {@link Integer#MAX_VALUE}.
+     * </p>
+     *
+     * @param <E>  The element type of the collections in the iterable.
+     * @param iterable the iterable of collections to sum the sizes of, must 
not be null.
+     * @return the sum of the sizes of the collections in the iterable, capped 
at {@link Integer#MAX_VALUE}.
+     * @since 4.6.0
+     */
+    public static <E> int sumSizesToInt(final Iterable<? extends 
Collection<E>> iterable) {
+        return sumToInt(iterable, Collection::size);
+    }
+
+    /**
+     * Returns the sum of the integer values produced by applying the given 
function to each element in the iterable.
+     * <p>
+     * Integer overflow is capped at {@link Integer#MAX_VALUE}.
+     * </p>
+     *
+     * @param <C>           The type of the elements in the iterable.
+     * @param iterable      The iterable of elements to sum the integer values 
of, must not be null.
+     * @param toIntFunction The function to apply to each element to produce 
an integer value, must not be null.
+     * @return the sum of the integer values produced by applying the function 
to each element in the iterable, capped at {@link Integer#MAX_VALUE}.
+     */
+    private static <C extends Collection<?>> int sumToInt(final Iterable<C> 
iterable, final ToIntFunction<C> toIntFunction) {
+        int size = 0;
+        try {
+            for (final C item : iterable) {
+                size = Math.addExact(size, toIntFunction.applyAsInt(item));
+            }
+        } catch (final ArithmeticException e) {
+            size = Integer.MAX_VALUE;
+        }
+        return size;
+    }
+
     /**
      * Gets a new list with the contents of the provided iterable.
      *
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
index 486e132b1..85cc3baa2 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
@@ -27,6 +27,7 @@ import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.iterators.EmptyIterator;
 import org.apache.commons.collections4.iterators.IteratorChain;
 import org.apache.commons.collections4.list.UnmodifiableList;
@@ -430,11 +431,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      */
     @Override
     public int size() {
-        long size = 0;
-        for (final Collection<E> item : all) {
-            size += item.size();
-        }
-        return (int) Math.min(size, Integer.MAX_VALUE);
+        return IterableUtils.sumSizesToInt(all);
     }
 
     /**
diff --git 
a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
 
b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
index 373f68716..cf8094f07 100644
--- 
a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
+++ 
b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
@@ -31,6 +31,7 @@ import java.util.Objects;
 import java.util.Set;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.collections4.MapIterator;
 import org.apache.commons.collections4.MultiSet;
@@ -903,11 +904,7 @@ public abstract class AbstractMultiValuedMap<K, V> 
implements MultiValuedMap<K,
         // but this requires that all modifications of the multimap
         // (including the wrapped collections and entry/value
         // collections) are tracked.
-        long size = 0;
-        for (final Collection<V> col : getMap().values()) {
-            size += col.size();
-        }
-        return (int) Math.min(size, Integer.MAX_VALUE);
+        return IterableUtils.sumSizesToInt(getMap().values());
     }
 
     @Override
diff --git 
a/src/main/java/org/apache/commons/collections4/multiset/AbstractMultiSet.java 
b/src/main/java/org/apache/commons/collections4/multiset/AbstractMultiSet.java
index 7de3788a5..ba6b739b9 100644
--- 
a/src/main/java/org/apache/commons/collections4/multiset/AbstractMultiSet.java
+++ 
b/src/main/java/org/apache/commons/collections4/multiset/AbstractMultiSet.java
@@ -475,16 +475,20 @@ public abstract class AbstractMultiSet<E> extends 
AbstractCollection<E> implemen
     /**
      * Returns the number of elements in this multiset.
      *
-     * @return current size of the multiset, or {@code Integer.MAX_VALUE}
-     *         if the total exceeds it
+     * @return current size of the multiset, or {@code Integer.MAX_VALUE} if 
the total exceeds it.
      */
     @Override
     public int size() {
-        long totalSize = 0;
-        for (final Entry<E> entry : entrySet()) {
-            totalSize += entry.getCount();
+        // TODO reuse IterableUtils.sum(Iterable, ToIntFunction)
+        int size = 0;
+        try {
+            for (final Entry<E> entry : entrySet()) {
+                size = Math.addExact(size, entry.getCount());
+            }
+        } catch (final ArithmeticException e) {
+            size = Integer.MAX_VALUE;
         }
-        return (int) Math.min(totalSize, Integer.MAX_VALUE);
+        return size;
     }
 
     /**
diff --git 
a/src/main/java/org/apache/commons/collections4/set/CompositeSet.java 
b/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
index 290606e29..5b3bed7bd 100644
--- a/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
+++ b/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.collection.CompositeCollection;
 import org.apache.commons.collections4.iterators.EmptyIterator;
 import org.apache.commons.collections4.iterators.IteratorChain;
@@ -470,11 +471,7 @@ public class CompositeSet<E> implements Set<E>, 
Serializable {
      */
     @Override
     public int size() {
-        long size = 0;
-        for (final Set<E> item : all) {
-            size += item.size();
-        }
-        return (int) Math.min(size, Integer.MAX_VALUE);
+        return IterableUtils.sumSizesToInt(all);
     }
 
     /**
diff --git 
a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
 
b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
index 46588a3d1..ed9663541 100644
--- 
a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
+++ 
b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
@@ -1293,6 +1293,7 @@ public abstract class AbstractMultiValuedMapTest<K, V> 
extends AbstractObjectTes
         map.put("k2", "v2");
         ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE 
- 1);
         ((HashBag<String>) map.getMap().get("k2")).add("v2", Integer.MAX_VALUE 
- 1);
+        ((HashBag<String>) map.getMap().get("k1")).add("v1", Integer.MAX_VALUE 
- 1);
         assertEquals(Integer.MAX_VALUE, map.size());
     }
 

Reply via email to