# Class MultiKeyMap<K,V>

java.lang.Object
org.apache.commons.collections4.map.AbstractIterableMap<MultiKey<? extends K>,V>
org.apache.commons.collections4.map.AbstractMapDecorator<MultiKey<? extends K>,V>
org.apache.commons.collections4.map.MultiKeyMap<K,V>

Type Parameters:
  `K` - the type of the keys in this map
  `V` - the type of the values in this map

All Implemented Interfaces:
  `Serializable`, `Cloneable`, `Map<MultiKey<? extends K>,V>`, `Get<MultiKey<? extends K>,V>`, `IterableGet<MultiKey<? extends K>,V>`, `IterableMap<MultiKey<? extends K>,V>`, `Put<MultiKey<? extends K>,V>`

public class MultiKeyMap<K,V> extends AbstractMapDecorator<MultiKey<? extends K>,V> implements Serializable, Cloneable
A `Map` implementation that uses multiple keys to map the value.

This class is the most efficient way to uses multiple keys to map to a value. The best way to use this class is via the additional map-style methods. These provide `get`, `containsKey`, `put` and `remove` for individual keys which operate without extra object creation.

The additional methods are the main interface of this map. As such, you will not normally hold this map in a variable of type `Map`.

The normal map methods take in and return a `MultiKey`. If you try to use `put()` with any other object type a `ClassCastException` is thrown. If you try to use `null` as the key in `put()` a `NullPointerException` is thrown.

This map is implemented as a decorator of a `AbstractHashedMap` which enables extra behavior to be added easily.

- `MultiKeyMap.decorate(new LinkedMap())` creates an ordered map.
- `MultiKeyMap.decorate(new LRUMap())` creates an least recently used map.
- `MultiKeyMap.decorate(new ReferenceMap())` creates a garbage collector sensitive map.

Note that `IdentityMap` and `ReferenceIdentityMap` are unsuitable for use as the key comparison would work on the whole MultiKey, not the elements within.

As an example, consider a least recently used cache that uses a String airline code and a Locale to lookup the airline's name:

     private MultiKeyMap cache = MultiKeyMap.multiKeyMap(new LRUMap(50));

     public String getAirlineName(String code, String locale) {
       String name = (String) cache.get(code, locale);
       if (name == null) {
         name = getAirlineNameFromDB(code, locale);
         cache.put(code, locale, name);
       }
       return name;
     }

Note that MultiKeyMap is not synchronized and is not thread-safe. If you wish to use this map from multiple threads concurrently, you must use appropriate synchronization. This class may throw exceptions when accessed by concurrent threads without synchronization.

Since:
  3.1
See Also:
  - Serialized Form

- ## Nested Class Summary

  ### Nested classes/interfaces inherited from interface java.util.Map

  `Map.Entry<K,V>`

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  ``
  `MultiKeyMap()`
  Constructs a new MultiKeyMap that decorates a `HashedMap`.
  `protected`
  `MultiKeyMap(AbstractHashedMap<MultiKey<? extends K>,V> map)`
  Constructor that decorates the specified map and is called from `multiKeyMap(AbstractHashedMap)`.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected void`
  `checkKey(MultiKey<?> key)`
  Check to ensure that input keys are valid MultiKey objects.
  `MultiKeyMap<K,V>`
  `clone()`
  Clones the map without cloning the keys or values.
  `boolean`
  `containsKey(Object key1, Object key2)`
  Checks whether the map contains the specified multi-key.
  `boolean`
  `containsKey(Object key1, Object key2, Object key3)`
  Checks whether the map contains the specified multi-key.
  `boolean`
  `containsKey(Object key1, Object key2, Object key3, Object key4)`
  Checks whether the map contains the specified multi-key.
  `boolean`
  `containsKey(Object key1, Object key2, Object key3, Object key4, Object key5)`
  Checks whether the map contains the specified multi-key.
  `protected AbstractHashedMap<MultiKey<? extends K>,V>`
  `decorated()`
  Gets the map being decorated.
  `V`
  `get(Object key1, Object key2)`
  Gets the value mapped to the specified multi-key.
  `V`
  `get(Object key1, Object key2, Object key3)`
  Gets the value mapped to the specified multi-key.
  `V`
  `get(Object key1, Object key2, Object key3, Object key4)`
  Gets the value mapped to the specified multi-key.
  `V`
  `get(Object key1, Object key2, Object key3, Object key4, Object key5)`
  Gets the value mapped to the specified multi-key.
  `protected int`
  `hash(Object key1, Object key2)`
  Gets the hash code for the specified multi-key.
  `protected int`
  `hash(Object key1, Object key2, Object key3)`
  Gets the hash code for the specified multi-key.
  `protected int`
  `hash(Object key1, Object key2, Object key3, Object key4)`
  Gets the hash code for the specified multi-key.
  `protected int`
  `hash(Object key1, Object key2, Object key3, Object key4, Object key5)`
  Gets the hash code for the specified multi-key.
  `protected boolean`
  `isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2)`
  Is the key equal to the combined key.
  `protected boolean`
  `isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3)`
  Is the key equal to the combined key.
  `protected boolean`
  `isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3, Object key4)`
  Is the key equal to the combined key.
  `protected boolean`
  `isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3, Object key4, Object key5)`
  Is the key equal to the combined key.
  `MapIterator<MultiKey<? extends K>,V>`
  `mapIterator()`
  Obtains a `MapIterator` over the map.
  `static <K, V> MultiKeyMap<K,V>`
  `multiKeyMap(AbstractHashedMap<MultiKey<? extends K>,V> map)`
  Decorates the specified map to add the MultiKeyMap API and fast query.
  `V`
  `put(K key1, K key2, K key3, K key4, K key5, V value)`
  Associates the specified value with the specified keys in this map.
  `V`
  `put(K key1, K key2, K key3, K key4, V value)`
  Associates the specified value with the specified keys in this map.
  `V`
  `put(K key1, K key2, K key3, V value)`
  Associates the specified value with the specified keys in this map.
  `V`
  `put(K key1, K key2, V value)`
  Associates the specified value with the specified keys in this map.
  `V`
  `put(MultiKey<? extends K> key, V value)`
  Puts the key and value into the map, where the key must be a non-null MultiKey object.
  `void`
  `putAll(Map<? extends MultiKey<? extends K>,? extends V> mapToCopy)`
  Copies all of the keys and values from the specified map to this map.
  `boolean`
  `removeAll(Object key1)`
  Removes all mappings where the first key is that specified.
  `boolean`
  `removeAll(Object key1, Object key2)`
  Removes all mappings where the first two keys are those specified.
  `boolean`
  `removeAll(Object key1, Object key2, Object key3)`
  Removes all mappings where the first three keys are those specified.
  `boolean`
  `removeAll(Object key1, Object key2, Object key3, Object key4)`
  Removes all mappings where the first four keys are those specified.
  `V`
  `removeMultiKey(Object key1, Object key2)`
  Removes the specified multi-key from this map.
  `V`
  `removeMultiKey(Object key1, Object key2, Object key3)`
  Removes the specified multi-key from this map.
  `V`
  `removeMultiKey(Object key1, Object key2, Object key3, Object key4)`
  Removes the specified multi-key from this map.
  `V`
  `removeMultiKey(Object key1, Object key2, Object key3, Object key4, Object key5)`
  Removes the specified multi-key from this map.

  ### Methods inherited from class org.apache.commons.collections4.map.AbstractMapDecorator

  `clear, containsKey, containsValue, entrySet, equals, get, hashCode, isEmpty, keySet, remove, size, toString, values`

  ### Methods inherited from class java.lang.Object

  `finalize, getClass, notify, notifyAll, wait, wait, wait`

  ### Methods inherited from interface java.util.Map

  `compute, computeIfAbsent, computeIfPresent, forEach, getOrDefault, merge, putIfAbsent, remove, replace, replace, replaceAll`

- ## Constructor Details

  - ### MultiKeyMap

    public MultiKeyMap()
    Constructs a new MultiKeyMap that decorates a `HashedMap`.

  - ### MultiKeyMap

    protected MultiKeyMap(AbstractHashedMap<MultiKey<? extends K>,V> map)
    Constructor that decorates the specified map and is called from `multiKeyMap(AbstractHashedMap)`. The map must not be null and should be empty or only contain valid keys. This constructor performs no validation.
    Parameters:
      `map` - the map to decorate

- ## Method Details

  - ### multiKeyMap

    public static <K, V> MultiKeyMap<K,V> multiKeyMap(AbstractHashedMap<MultiKey<? extends K>,V> map)
    Decorates the specified map to add the MultiKeyMap API and fast query. The map must not be null and must be empty.
    Type Parameters:
      `K` - the key type
      `V` - the value type
    Parameters:
      `map` - the map to decorate, not null
    Returns:
      a new multi key map
    Throws:
      `NullPointerException` - if map is null
      `IllegalArgumentException` - if the map is not empty
    Since:
      4.0

  - ### checkKey

    protected void checkKey(MultiKey<?> key)
    Check to ensure that input keys are valid MultiKey objects.
    Parameters:
      `key` - the key to check

  - ### clone

    public MultiKeyMap<K,V> clone()
    Clones the map without cloning the keys or values.
    Overrides:
      `clone` in class `Object`
    Returns:
      a shallow clone

  - ### containsKey

    public boolean containsKey(Object key1, Object key2)
    Checks whether the map contains the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
    Returns:
      true if the map contains the key

  - ### containsKey

    public boolean containsKey(Object key1, Object key2, Object key3)
    Checks whether the map contains the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      true if the map contains the key

  - ### containsKey

    public boolean containsKey(Object key1, Object key2, Object key3, Object key4)
    Checks whether the map contains the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      true if the map contains the key

  - ### containsKey

    public boolean containsKey(Object key1, Object key2, Object key3, Object key4, Object key5)
    Checks whether the map contains the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
    Returns:
      true if the map contains the key

  - ### decorated

    protected AbstractHashedMap<MultiKey<? extends K>,V> decorated()
    Gets the map being decorated.
    Overrides:
      `decorated` in class `AbstractMapDecorator<MultiKey<? extends K>,V>`
    Returns:
      the decorated map

  - ### get

    public V get(Object key1, Object key2)
    Gets the value mapped to the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
    Returns:
      the mapped value, null if no match

  - ### get

    public V get(Object key1, Object key2, Object key3)
    Gets the value mapped to the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      the mapped value, null if no match

  - ### get

    public V get(Object key1, Object key2, Object key3, Object key4)
    Gets the value mapped to the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      the mapped value, null if no match

  - ### get

    public V get(Object key1, Object key2, Object key3, Object key4, Object key5)
    Gets the value mapped to the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
    Returns:
      the mapped value, null if no match

  - ### hash

    protected int hash(Object key1, Object key2)
    Gets the hash code for the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
    Returns:
      the hash code

  - ### hash

    protected int hash(Object key1, Object key2, Object key3)
    Gets the hash code for the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      the hash code

  - ### hash

    protected int hash(Object key1, Object key2, Object key3, Object key4)
    Gets the hash code for the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      the hash code

  - ### hash

    protected int hash(Object key1, Object key2, Object key3, Object key4, Object key5)
    Gets the hash code for the specified multi-key.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
    Returns:
      the hash code

  - ### isEqualKey

    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2)
    Is the key equal to the combined key.
    Parameters:
      `entry` - the entry to compare to
      `key1` - the first key
      `key2` - the second key
    Returns:
      true if the key matches

  - ### isEqualKey

    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3)
    Is the key equal to the combined key.
    Parameters:
      `entry` - the entry to compare to
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      true if the key matches

  - ### isEqualKey

    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3, Object key4)
    Is the key equal to the combined key.
    Parameters:
      `entry` - the entry to compare to
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      true if the key matches

  - ### isEqualKey

    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>,V> entry, Object key1, Object key2, Object key3, Object key4, Object key5)
    Is the key equal to the combined key.
    Parameters:
      `entry` - the entry to compare to
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
    Returns:
      true if the key matches

  - ### mapIterator

    public MapIterator<MultiKey<? extends K>,V> mapIterator()
    Description copied from class: `AbstractIterableMap`
    Obtains a `MapIterator` over the map.

    A map iterator is an efficient way of iterating over maps. There is no need to access the entry set or use Map Entry objects.

         IterableMap<String,Integer> map = new HashedMap<String,Integer>();
         MapIterator<String,Integer> it = map.mapIterator();
         while (it.hasNext()) {
           String key = it.next();
           Integer value = it.getValue();
           it.setValue(value + 1);
         }

    Specified by:
      `mapIterator` in interface `IterableGet<K,V>`
    Overrides:
      `mapIterator` in class `AbstractIterableMap<MultiKey<? extends K>,V>`
    Returns:
      a map iterator

  - ### put

    public V put(K key1, K key2, K key3, K key4, K key5, V value)
    Associates the specified value with the specified keys in this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
      `value` - the value to store
    Returns:
      the value previously mapped to this combined key, null if none

  - ### put

    public V put(K key1, K key2, K key3, K key4, V value)
    Associates the specified value with the specified keys in this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `value` - the value to store
    Returns:
      the value previously mapped to this combined key, null if none

  - ### put

    public V put(K key1, K key2, K key3, V value)
    Associates the specified value with the specified keys in this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `value` - the value to store
    Returns:
      the value previously mapped to this combined key, null if none

  - ### put

    public V put(K key1, K key2, V value)
    Associates the specified value with the specified keys in this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `value` - the value to store
    Returns:
      the value previously mapped to this combined key, null if none

  - ### put

    public V put(MultiKey<? extends K> key, V value)
    Puts the key and value into the map, where the key must be a non-null MultiKey object.
    Specified by:
      `put` in interface `Map<K,V>`
    Specified by:
      `put` in interface `Put<K,V>`
    Overrides:
      `put` in class `AbstractMapDecorator<MultiKey<? extends K>,V>`
    Parameters:
      `key` - the non-null MultiKey object
      `value` - the value to store
    Returns:
      the previous value for the key
    Throws:
      `NullPointerException` - if the key is null
      `ClassCastException` - if the key is not a MultiKey
    See Also:
      - `Map.put(Object, Object)`

  - ### putAll

    public void putAll(Map<? extends MultiKey<? extends K>,? extends V> mapToCopy)
    Copies all of the keys and values from the specified map to this map. Each key must be non-null and a MultiKey object.
    Specified by:
      `putAll` in interface `Map<K,V>`
    Specified by:
      `putAll` in interface `Put<K,V>`
    Overrides:
      `putAll` in class `AbstractMapDecorator<MultiKey<? extends K>,V>`
    Parameters:
      `mapToCopy` - to this map
    Throws:
      `NullPointerException` - if the mapToCopy or any key within is null
      `ClassCastException` - if any key in mapToCopy is not a MultiKey
    See Also:
      - `Map.putAll(Map)`

  - ### removeAll

    public boolean removeAll(Object key1)
    Removes all mappings where the first key is that specified.

    This method removes all the mappings where the `MultiKey` has one or more keys, and the first matches that specified.

    Parameters:
      `key1` - the first key
    Returns:
      true if any elements were removed

  - ### removeAll

    public boolean removeAll(Object key1, Object key2)
    Removes all mappings where the first two keys are those specified.

    This method removes all the mappings where the `MultiKey` has two or more keys, and the first two match those specified.

    Parameters:
      `key1` - the first key
      `key2` - the second key
    Returns:
      true if any elements were removed

  - ### removeAll

    public boolean removeAll(Object key1, Object key2, Object key3)
    Removes all mappings where the first three keys are those specified.

    This method removes all the mappings where the `MultiKey` has three or more keys, and the first three match those specified.

    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      true if any elements were removed

  - ### removeAll

    public boolean removeAll(Object key1, Object key2, Object key3, Object key4)
    Removes all mappings where the first four keys are those specified.

    This method removes all the mappings where the `MultiKey` has four or more keys, and the first four match those specified.

    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      true if any elements were removed

  - ### removeMultiKey

    public V removeMultiKey(Object key1, Object key2)
    Removes the specified multi-key from this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
    Returns:
      the value mapped to the removed key, null if key not in map
    Since:
      4.0 (previous name: remove(Object, Object))

  - ### removeMultiKey

    public V removeMultiKey(Object key1, Object key2, Object key3)
    Removes the specified multi-key from this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
    Returns:
      the value mapped to the removed key, null if key not in map
    Since:
      4.0 (previous name: remove(Object, Object, Object))

  - ### removeMultiKey

    public V removeMultiKey(Object key1, Object key2, Object key3, Object key4)
    Removes the specified multi-key from this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
    Returns:
      the value mapped to the removed key, null if key not in map
    Since:
      4.0 (previous name: remove(Object, Object, Object, Object))

  - ### removeMultiKey

    public V removeMultiKey(Object key1, Object key2, Object key3, Object key4, Object key5)
    Removes the specified multi-key from this map.
    Parameters:
      `key1` - the first key
      `key2` - the second key
      `key3` - the third key
      `key4` - the fourth key
      `key5` - the fifth key
    Returns:
      the value mapped to the removed key, null if key not in map
    Since:
      4.0 (previous name: remove(Object, Object, Object, Object, Object))