Class MultiSet<E>

java.lang.Object
java.util.AbstractCollection<E>
java.util.AbstractSet<E>
org.apache.juneau.commons.collections.MultiSet<E>
Type Parameters:
E - The element type of this set.
All Implemented Interfaces:
Iterable<E>, Collection<E>, Set<E>

public class MultiSet<E> extends AbstractSet<E>
A composite set that presents multiple collections as a single unified set.

This class allows multiple collections to be viewed and iterated over as if they were merged into a single set, without actually copying the elements. Modifications made through the iterator affect the underlying collections.

Features:
  • Zero-Copy Composition: No data is copied when creating a MultiSet; it simply wraps the provided collections
  • Transparent Iteration: Iterating over a MultiSet seamlessly traverses all underlying collections in order
  • Modification Support: Elements can be removed via the iterator's Iterator.remove() method
  • Efficient Size Calculation: The size is computed by summing the sizes of all underlying collections
  • Enumeration Support: Provides an Enumeration view via enumerator()
Usage:

// Create a MultiSet from three separate collections List<String> list1 = List.of("a", "b"); Set<String> set1 = Set.of("c", "d"); List<String> list2 = List.of("e", "f"); MultiSet<String> multiSet = new MultiSet<>(list1, set1, list2); // Iterate over all elements from all collections for (String element : multiSet) { System.out.println(element); // Prints: a, b, c, d, e, f } // Get total size across all collections int totalSize = multiSet.size(); // Returns: 6 // Remove elements via iterator (affects underlying collections) Iterator<String> it = multiSet.iterator(); while (it.hasNext()) { if (it.next().equals("b")) { it.remove(); // Removes "b" from list1 } }

Behavior Notes:
  • The order of iteration follows the order of collections as provided in the constructor
  • Within each collection, iteration order is determined by that collection's iterator
  • The underlying collections must not be null, but can be empty
  • Modifications via Iterator.remove() are delegated to the underlying collection's iterator
  • This class does not support AbstractCollection.add(Object) or AbstractCollection.remove(Object) operations
  • The size() method recomputes the sum each time it's called (not cached)
Thread Safety:

This class is not inherently thread-safe. If the underlying collections are modified concurrently during iteration, the behavior is undefined. Synchronization must be handled externally if needed.

Example - Processing Multiple Data Sources:

// Combine results from database, cache, and defaults List<User> dbUsers = fetchFromDatabase(); Set<User> cachedUsers = getCachedUsers(); List<User> defaultUsers = getDefaultUsers(); MultiSet<User> allUsers = new MultiSet<>(dbUsers, cachedUsers, defaultUsers); // Process all users from all sources allUsers.forEach(user -> processUser(user));

See Also:
  • Constructor Details

    • MultiSet

      Creates a new MultiSet that presents the specified collections as a single unified set.

      The collections are stored by reference (not copied), so modifications made through the MultiSet's iterator will affect the original collections.

      Example:

      List<String> list1 = new ArrayList<>(List.of("a", "b")); List<String> list2 = new ArrayList<>(List.of("c", "d")); MultiSet<String> multiSet = new MultiSet<>(list1, list2); // multiSet now represents all elements from both lists

      Parameters:
      c - Zero or more collections to combine into this set. Must not be null, and no individual collection can be null (but collections can be empty).
      Throws:
      IllegalArgumentException - if the collections array or any collection within it is null.
  • Method Details

    • enumerator

      Returns an Enumeration view of this set.

      This is useful for compatibility with legacy APIs that require an Enumeration rather than an Iterator.

      Example:

      MultiSet<String> multiSet = new MultiSet<>(list1, list2); Enumeration<String> enumeration = multiSet.enumerator(); while (enumeration.hasMoreElements()) { String element = enumeration.nextElement(); // Process element }

      Returns:
      An Enumeration that iterates over all elements in all underlying collections.
      See Also:
    • iterator

      public Iterator<E> iterator()
      Returns an iterator over all elements in all underlying collections.

      The iterator traverses each collection in the order they were provided to the constructor. Within each collection, the iteration order is determined by that collection's iterator.

      The returned iterator supports the Iterator.remove() operation, which removes the current element from its underlying collection.

      Behavior:
      Example:

      List<String> list1 = new ArrayList<>(List.of("a", "b")); List<String> list2 = new ArrayList<>(List.of("c", "d")); MultiSet<String> multiSet = new MultiSet<>(list1, list2); Iterator<String> it = multiSet.iterator(); while (it.hasNext()) { String element = it.next(); if (element.equals("b")) { it.remove(); // Removes "b" from list1 } }

      Specified by:
      iterator in interface Collection<E>
      Specified by:
      iterator in interface Iterable<E>
      Specified by:
      iterator in interface Set<E>
      Specified by:
      iterator in class AbstractCollection<E>
      Returns:
      An iterator over all elements in all underlying collections.
    • size

      public int size()
      Returns the total number of elements across all underlying collections.

      This method computes the size by summing the Collection.size() of each underlying collection. The size is recalculated each time this method is called (it is not cached).

      Example:

      List<String> list1 = List.of("a", "b"); // size = 2 List<String> list2 = List.of("c", "d", "e"); // size = 3 MultiSet<String> multiSet = new MultiSet<>(list1, list2); int totalSize = multiSet.size(); // Returns: 5

      Specified by:
      size in interface Collection<E>
      Specified by:
      size in interface Set<E>
      Specified by:
      size in class AbstractCollection<E>
      Returns:
      The sum of sizes of all underlying collections.
    • toString

      public String toString()
      Returns a string representation of this MultiSet.

      The format is "[[...],[...],...]" where each [...] is the standard standard string representation of each underlying collection (as returned by Object.toString()).

      Example:

      List<String> list1 = List.of("a", "b"); List<String> list2 = List.of("c", "d"); MultiSet<String> multiSet = new MultiSet<>(list1, list2); multiSet.toString(); // Returns: "[[a, b], [c, d]]"

      Overrides:
      toString in class AbstractCollection<E>
      Returns:
      A string representation of this MultiSet.
    • equals

      public boolean equals(Object o)
      Compares the specified object with this set for equality.

      Returns true if the given object is also a set, the two sets have the same size, and every member of the given set is contained in this set.

      This implementation checks if the specified object is a set, and if so, compares the sizes and checks if all elements in the specified set are contained in this set.

      Specified by:
      equals in interface Collection<E>
      Specified by:
      equals in interface Set<E>
      Overrides:
      equals in class AbstractSet<E>
      Parameters:
      o - Object to be compared for equality with this set.
      Returns:
      true if the specified object is equal to this set.
    • hashCode

      public int hashCode()
      Returns the hash code value for this set.

      The hash code of a set is defined to be the sum of the hash codes of the elements in the set, where the hash code of a null element is defined to be zero. This ensures that s1.equals(s2) implies that s1.hashCode()==s2.hashCode() for any two sets s1 and s2, as required by the general contract of Object.hashCode().

      This implementation iterates over the set, calling the hashCode method on each element in the set, and adding up the results.

      Specified by:
      hashCode in interface Collection<E>
      Specified by:
      hashCode in interface Set<E>
      Overrides:
      hashCode in class AbstractSet<E>
      Returns:
      The hash code value for this set.