Class MultiMap<K,V>

java.lang.Object
java.util.AbstractMap<K,V>
org.apache.juneau.commons.collections.MultiMap<K,V>
Type Parameters:
K - The key type of this map.
V - The value type of this map.
All Implemented Interfaces:
Map<K,V>

public class MultiMap<K,V> extends AbstractMap<K,V>
A composite map that presents multiple maps as a single unified map.

This class allows multiple maps to be viewed and accessed as if they were merged into a single map, without actually copying the entries. When the same key exists in multiple maps, the value from the first map (in constructor order) is returned.

Features:
  • Zero-Copy Composition: No data is copied when creating a MultiMap; it simply wraps the provided maps
  • Transparent Access: Accessing entries by key seamlessly searches all underlying maps in order
  • First-Wins Semantics: When a key exists in multiple maps, the value from the first map is returned
  • Modification Support: Entries can be removed via the iterator's Iterator.remove() method
  • Efficient Size Calculation: The size is computed by counting unique keys across all maps
Usage:

// Create a MultiMap from three separate maps Map<String, String> map1 = Map.of("key1", "value1", "key2", "value2"); Map<String, String> map2 = Map.of("key3", "value3", "key2", "value2b"); Map<String, String> map3 = Map.of("key4", "value4"); MultiMap<String, String> multiMap = new MultiMap<>(map1, map2, map3); // Access entries by key multiMap.get("key1"); // Returns "value1" from map1 multiMap.get("key2"); // Returns "value2" from map1 (first match wins) multiMap.get("key3"); // Returns "value3" from map2 // Iterate over all entries from all maps for (Map.Entry<String, String> entry : multiMap.entrySet()) { System.out.println(entry); // Prints entries from all maps } // Get total size (unique keys across all maps) int totalSize = multiMap.size(); // Returns: 4 (key1, key2, key3, key4)

Behavior Notes:
  • The order of key lookup follows the order of maps as provided in the constructor
  • When a key exists in multiple maps, get(Object) returns the value from the first map containing that key
  • The underlying maps must not be null, but can be empty
  • Modifications via Iterator.remove() are delegated to the underlying map's entry set iterator
  • This class does not support put(Object, Object), remove(Object), or clear() operations
  • The size() method recomputes the count of unique keys each time it's called (not cached)
  • The entrySet() iterator only returns each key once (first occurrence), even if it exists in multiple maps
Thread Safety:

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

Example - Processing Multiple Configuration Sources:

// Combine configuration from system properties, environment, and defaults Map<String, String> systemProps = getSystemProperties(); Map<String, String> envVars = getEnvironmentVariables(); Map<String, String> defaults = getDefaultConfig(); MultiMap<String, String> config = new MultiMap<>(systemProps, envVars, defaults); // Access configuration (system props take precedence, then env vars, then defaults) String host = config.get("host");

See Also:
  • Constructor Details

    • MultiMap

      @SafeVarargs public MultiMap(Map<K,V>... maps)
      Creates a new MultiMap that presents the specified maps as a single unified map.

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

      Example:

      Map<String, String> map1 = new LinkedHashMap<>(Map.of("a", "1")); Map<String, String> map2 = new LinkedHashMap<>(Map.of("b", "2")); MultiMap<String, String> multiMap = new MultiMap<>(map1, map2); // multiMap now represents all entries from both maps

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

    • get

      public V get(Object key)
      Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

      This method searches the underlying maps in the order they were provided to the constructor. The first map containing the key determines the returned value.

      Specified by:
      get in interface Map<K,V>
      Overrides:
      get in class AbstractMap<K,V>
      Parameters:
      key - The key whose associated value is to be returned.
      Returns:
      The value to which the specified key is mapped, or null if this map contains no mapping for the key.
    • containsKey

      public boolean containsKey(Object key)
      Returns true if this map contains a mapping for the specified key.
      Specified by:
      containsKey in interface Map<K,V>
      Overrides:
      containsKey in class AbstractMap<K,V>
      Parameters:
      key - The key whose presence in this map is to be tested.
      Returns:
      true if this map contains a mapping for the specified key.
    • containsValue

      public boolean containsValue(Object value)
      Returns true if this map maps one or more keys to the specified value.
      Specified by:
      containsValue in interface Map<K,V>
      Overrides:
      containsValue in class AbstractMap<K,V>
      Parameters:
      value - The value whose presence in this map is to be tested.
      Returns:
      true if this map maps one or more keys to the specified value.
    • entrySet

      public Set<Map.Entry<K,V>> entrySet()
      Returns a Set view of the mappings contained in this map.

      The returned set is a composite view of all underlying maps. When a key exists in multiple maps, only the entry from the first map (in constructor order) is included.

      The iterator supports the Iterator.remove() operation, which removes the entry from its underlying map.

      Specified by:
      entrySet in interface Map<K,V>
      Specified by:
      entrySet in class AbstractMap<K,V>
      Returns:
      A set view of the mappings contained in this map.
    • size

      public int size()
      Returns the number of unique key-value mappings in this map.

      This method computes the size by counting unique keys across all underlying maps. If a key exists in multiple maps, it is counted only once. The size is recalculated each time this method is called (it is not cached).

      Example:

      Map<String, String> map1 = Map.of("a", "1", "b", "2"); // size = 2 Map<String, String> map2 = Map.of("b", "3", "c", "4"); // size = 2 MultiMap<String, String> multiMap = new MultiMap<>(map1, map2); int totalSize = multiMap.size(); // Returns: 3 (a, b, c - b is counted only once)

      Specified by:
      size in interface Map<K,V>
      Overrides:
      size in class AbstractMap<K,V>
      Returns:
      The number of unique key-value mappings in this map.
    • isEmpty

      public boolean isEmpty()
      Returns true if this map contains no key-value mappings.
      Specified by:
      isEmpty in interface Map<K,V>
      Overrides:
      isEmpty in class AbstractMap<K,V>
      Returns:
      true if this map contains no key-value mappings.
    • values

      public Collection<V> values()
      Returns a Collection view of the values contained in this map.

      The returned collection is a view of the values from the entries in entrySet(). When a key exists in multiple maps, only the value from the first map (in constructor order) is included.

      Specified by:
      values in interface Map<K,V>
      Overrides:
      values in class AbstractMap<K,V>
      Returns:
      A collection view of the values contained in this map.
    • put

      public V put(K key, V value)
      Specified by:
      put in interface Map<K,V>
      Overrides:
      put in class AbstractMap<K,V>
    • remove

      public V remove(Object key)
      Specified by:
      remove in interface Map<K,V>
      Overrides:
      remove in class AbstractMap<K,V>
    • putAll

      public void putAll(Map<? extends K,? extends V> m)
      Specified by:
      putAll in interface Map<K,V>
      Overrides:
      putAll in class AbstractMap<K,V>
    • clear

      public void clear()
      Specified by:
      clear in interface Map<K,V>
      Overrides:
      clear in class AbstractMap<K,V>
    • toString

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

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

      Example:

      Map<String, String> map1 = Map.of("a", "1"); Map<String, String> map2 = Map.of("b", "2"); MultiMap<String, String> multiMap = new MultiMap<>(map1, map2); multiMap.toString(); // Returns: "[{a=1}, {b=2}]"

      Overrides:
      toString in class AbstractMap<K,V>
      Returns:
      A string representation of this MultiMap.
    • equals

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

      Returns true if the given object is also a map and the two maps represent the same mappings. More formally, two maps m1 and m2 represent the same mappings if m1.entrySet().equals(m2.entrySet()).

      This implementation compares the entry sets of the two maps.

      Specified by:
      equals in interface Map<K,V>
      Overrides:
      equals in class AbstractMap<K,V>
      Parameters:
      o - Object to be compared for equality with this map.
      Returns:
      true if the specified object is equal to this map.
    • hashCode

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

      The hash code of a map is defined to be the sum of the hash codes of each entry in the map's entrySet() view. This ensures that m1.equals(m2) implies that m1.hashCode()==m2.hashCode() for any two maps m1 and m2, as required by the general contract of Object.hashCode().

      This implementation computes the hash code from the entry set.

      Specified by:
      hashCode in interface Map<K,V>
      Overrides:
      hashCode in class AbstractMap<K,V>
      Returns:
      The hash code value for this map.