qflib 0.98.1

de.qfs.lib.util
Class MultiMap

java.lang.Object
  |
  +--de.qfs.lib.util.MultiMap
All Implemented Interfaces:
java.lang.Cloneable, java.util.Map, java.io.Serializable

public class MultiMap
extends java.lang.Object
implements java.util.Map, java.lang.Cloneable, java.io.Serializable

This is a special implementation of the Map interface that can store more than one value per key. When a value is retrieved with get, an arbitrary one is returned if more than one is available.

The remove(key) removes all values stored for that key. To remove only a single value, use the remove(key,value) method.

Since:
0.98.0
Version:
$Revision: 1.5 $
Author:
Gregor Schmid
See Also:
Serialized Form

Inner Class Summary
protected  class MultiMap.MapEntry
          An implementation of the Map.Entry interface.
protected  class MultiMap.MapIterator
          Iterator for the key, value and entry collections of the MultiMap.
static class MultiMap.UnitTest
          Test cases for the MultiMap class.
protected static interface MultiMap.ValueSet
          This interface is a marker for the actual Set used to store multiple values for the same key in a MultiMap.
 
Inner classes inherited from class java.util.Map
java.util.Map.Entry
 
Field Summary
protected static int ENTRIES
          Type selector for an entry iterator.
protected  java.util.Set entrySet
          The Set returned by entrySet.
protected static int KEYS
          Type selector for a key iterator.
protected  java.util.Set keySet
          The Set returned by keySet.
protected  int modCounter
          Since HashMap's modification counter is private the MultiMap needs its own.
protected  int valCount
          Number of values stored in the MultiMap.
protected  java.util.Collection values
          The Collection returned by values.
protected static int VALUES
          Type selector for a value iterator.
 
Constructor Summary
MultiMap()
          Create a new MultiMap.
MultiMap(int initialCapacity)
          Create a new MultiMap.
MultiMap(java.util.Map map)
          Create a new MultiMap and initialize it with all the mappings from the passed map.
 
Method Summary
protected  boolean _remove(java.lang.Object key, java.lang.Object value)
          This is the actual implementation of the remove(Object,Object) method.
protected  boolean areEqual(java.lang.Object o1, java.lang.Object o2)
          Compare two objects.
 void clear()
          Removes all mappings from this map.
 java.lang.Object clone()
          Returns a shallow copy of this MultiMap: the keys and values themselves are not cloned.
protected  java.util.Map cloneDelegate()
          This method is used by the clone method to create a copy of the delegate.
 boolean containsKey(java.lang.Object key)
          Returns true if this map contains a mapping for the specified key.
 boolean containsValue(java.lang.Object value)
          Returns true if this map maps one or more keys to the specified value.
protected  MultiMap.ValueSet createValueSet()
          This method creates a new ValueSet to store multiple values for the same key.
 java.util.Set entrySet()
          Returns a set view of the mappings contained in this map.
 boolean equals(java.lang.Object o)
          Test whether an object is equal to the MultiMap.
 java.lang.Object get(java.lang.Object key)
          Returns the value to which this map maps the specified key.
 java.util.Set getAll(java.lang.Object key)
          Get a Set of all Objects to which this map maps the key.
 int hashCode()
          Get the hashCode of the MultiMap.
 boolean isEmpty()
          Returns true if this map contains no key-value mappings.
 java.util.Set keySet()
          Returns a set view of the keys contained in this map.
 boolean mapsToMany(java.lang.Object key)
          Query whether a key maps to more than one values.
 java.lang.Object put(java.lang.Object key, java.lang.Object value)
          Associates the specified value with the specified key in this map.
 void putAll(java.util.Map map)
          Copies all of the mappings from the specified map to this map.
 java.lang.Object remove(java.lang.Object key)
          Removes all mappings for this key from this map if present.
 boolean remove(java.lang.Object key, java.lang.Object value)
          In contrast to remove(Object) this method removes only the one binding for key and value.
 int size()
          Returns the number of key-value mappings in this map.
 java.util.Collection values()
          Returns a collection view of the values contained in this map.
 
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

KEYS

protected static final int KEYS
Type selector for a key iterator.

VALUES

protected static final int VALUES
Type selector for a value iterator.

ENTRIES

protected static final int ENTRIES
Type selector for an entry iterator.

valCount

protected int valCount
Number of values stored in the MultiMap.

keySet

protected transient java.util.Set keySet
The Set returned by keySet.

values

protected transient java.util.Collection values
The Collection returned by values.

entrySet

protected transient java.util.Set entrySet
The Set returned by entrySet.

modCounter

protected transient int modCounter
Since HashMap's modification counter is private the MultiMap needs its own.
Constructor Detail

MultiMap

public MultiMap()
Create a new MultiMap.

MultiMap

public MultiMap(int initialCapacity)
Create a new MultiMap.
Parameters:
initialCapacity - The initial capacity of the MultiMap.

MultiMap

public MultiMap(java.util.Map map)
Create a new MultiMap and initialize it with all the mappings from the passed map.
Parameters:
map - The map that initializes this MultiMap.
Method Detail

isEmpty

public boolean isEmpty()
Returns true if this map contains no key-value mappings.
Specified by:
isEmpty in interface java.util.Map
Returns:
true if this map contains no key-value mappings.

size

public int size()
Returns the number of key-value mappings in this map. If the map contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
Specified by:
size in interface java.util.Map
Returns:
the number of key-value mappings in this map.

get

public java.lang.Object get(java.lang.Object key)
Returns the value to which this map maps the specified key. If more than one value is found, an arbitrary one is chosen. Returns null if the map contains no mapping for this key. A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.
Specified by:
get in interface java.util.Map
Parameters:
key - key whose associated value is to be returned.
Returns:
the value to which this map maps the specified key, or null if the map contains no mapping for this key.
See Also:
containsKey(Object)

containsKey

public boolean containsKey(java.lang.Object key)
Returns true if this map contains a mapping for the specified key.
Specified by:
containsKey in interface java.util.Map
Parameters:
key - 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(java.lang.Object value)
Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that (value==null ? v==null : value.equals(v)). This operation does require time linear in the map size.
Specified by:
containsValue in interface java.util.Map
Parameters:
value - value whose presence in this map is to be tested.
Returns:
true if this map maps one or more keys to the specified value.

put

public java.lang.Object put(java.lang.Object key,
                            java.lang.Object value)
Associates the specified value with the specified key in this map. If the map previously contained a mapping for this key, the old value is NOT replaced.
Specified by:
put in interface java.util.Map
Parameters:
key - key with which the specified value is to be associated.
value - value to be associated with the specified key.
Returns:
Since no value is ever replaced, this method always returns null.

putAll

public void putAll(java.util.Map map)
Copies all of the mappings from the specified map to this map.
Specified by:
putAll in interface java.util.Map
Parameters:
map - Mappings to be stored in this map.

remove

public java.lang.Object remove(java.lang.Object key)
Removes all mappings for this key from this map if present.
Specified by:
remove in interface java.util.Map
Parameters:
key - key whose mapping is to be removed from the map.
Returns:
previous value associated with specified key, or null if there was no mapping for key. If there was more than one mapping, an arbitrary one is choden for the return value. A null return can also indicate that the map previously associated null with the specified key.

clear

public void clear()
Removes all mappings from this map.
Specified by:
clear in interface java.util.Map

keySet

public java.util.Set keySet()
Returns a set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress, the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll retainAll, and clear operations. It does not support the add or addAll operations.
Specified by:
keySet in interface java.util.Map
Returns:
a set view of the keys contained in this map.

values

public java.util.Collection values()
Returns a collection view of the values contained in this map. The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa. If the map is modified while an iteration over the collection is in progress, the results of the iteration are undefined. The collection supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Collection.remove, removeAll, retainAll and clear operations. It does not support the add or addAll operations.
Specified by:
values in interface java.util.Map
Returns:
A collection view of the values contained in this map.

entrySet

public java.util.Set entrySet()
Returns a set view of the mappings contained in this map. Each element in the returned set is a Map.Entry. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress, the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll and clear operations. It does not support the add or addAll operations.
Specified by:
entrySet in interface java.util.Map
Returns:
a set view of the mappings contained in this map.

equals

public boolean equals(java.lang.Object o)
Test whether an object is equal to the MultiMap. As required by the Map interface, the object is considered euqal, if it is a Map whose entrySet is equal to the MultiMap's entrySet.
Specified by:
equals in interface java.util.Map
Overrides:
equals in class java.lang.Object
Parameters:
o - The object to compare to.
Returns:
True if the object is considered equal to the Map.

hashCode

public int hashCode()
Get the hashCode of the MultiMap. As required by the Map interface, this is the sum of the hashCodes of the MultiMap's entrySet.
Specified by:
hashCode in interface java.util.Map
Overrides:
hashCode in class java.lang.Object
Returns:
The MultiMap's hashCode.

clone

public java.lang.Object clone()
                       throws java.lang.ClassCastException
Returns a shallow copy of this MultiMap: the keys and values themselves are not cloned. If a derived class uses a delegate that is not a HashMap, it must override cloneDelegate, otherwise this method will fail with a ClassCastException.
Overrides:
clone in class java.lang.Object
Returns:
a shallow copy of this map.
Throws:
java.lang.ClassCastException - If the delegate is not a HashMap and the derived class doesn't override cloneDelegate.

remove

public boolean remove(java.lang.Object key,
                      java.lang.Object value)
In contrast to remove(Object) this method removes only the one binding for key and value.

Since this method is not part of the standard Map interface, it cannot directly be synchronized like all the others with the help of a Collections.SynchronizedMap. Nevertheless you can use a SynchronizedMap wrapper around the MultiMap for synchronized standard Map access and explicitely synchronize on that SynchronizedMap when calling this method.

Parameters:
key - The key of the binding to remove.
value - The value of the binding to remove.
Returns:
True if there really was a binding removed, false otherwise.

mapsToMany

public boolean mapsToMany(java.lang.Object key)
Query whether a key maps to more than one values.

Since this method is not part of the standard Map interface, it cannot directly be synchronized like all the others with the help of a Collections.SynchronizedMap. Nevertheless you can use a SynchronizedMap wrapper around the MultiMap for synchronized standard Map access and explicitely synchronize on that SynchronizedMap when calling this method.

Parameters:
key - The key to look for.
Returns:
True if there is more than one value bound for the key, false if the key is either unknown or has only single value.

getAll

public java.util.Set getAll(java.lang.Object key)
Get a Set of all Objects to which this map maps the key. Returns null if the map contains no mapping for this key. The result is a clone of the actual Set used and may be modified without changing the MultiMap.

Since this method is not part of the standard Map interface, it cannot directly be synchronized like all the others with the help of a Collections.SynchronizedMap. Nevertheless you can use a SynchronizedMap wrapper around the MultiMap for synchronized standard Map access and explicitely synchronize on that SynchronizedMap when calling this method.

Note: Though a set backed by the map would have been nice, the implications of modification to the set are not quite clear and difficult to implement. Maybe in a later version.

Parameters:
key - key whose associated values are to be returned.
Returns:
the set of values to which this map maps the specified key, or null if the map contains no mapping for this key.

createValueSet

protected MultiMap.ValueSet createValueSet()
This method creates a new ValueSet to store multiple values for the same key. The default is to use a NestedSet which extends HashSet. By overriding this method, a derived class can change the implementation of the ValueSet used by the MultiMap.
Returns:
A new ValueSet.

cloneDelegate

protected java.util.Map cloneDelegate()
                               throws java.lang.ClassCastException
This method is used by the clone method to create a copy of the delegate. If a derived class uses a delegate that is not a HashMap it needs to override this method, otherwise clone will result in a ClassCastException.
Returns:
A copy of the delegate.
Throws:
java.lang.ClassCastException - If the delegate is not a HashMap and the derived class doesn't override cloneDelegate.

areEqual

protected final boolean areEqual(java.lang.Object o1,
                                 java.lang.Object o2)
Compare two objects.
Parameters:
o1 - The first object.
o2 - The second object.
Returns:
True if both objects are null or one equals the other.

_remove

protected boolean _remove(java.lang.Object key,
                          java.lang.Object value)
This is the actual implementation of the remove(Object,Object) method.
Parameters:
key - The key of the binding to remove.
value - The value of the binding to remove.
Returns:
True if there really was a binding removed, false otherwise.

qflib 0.98.1