@GwtCompatible(serializable=true, emulated=true) public class LinkedListMultimap<K,V> extends AbstractMultimap<K,V> implements ListMultimap<K,V>, java.io.Serializable
ListMultimap
that supports deterministic
iteration order for both keys and values. The iteration order is preserved
across non-distinct key values. For example, for the following multimap
definition:
Multimap<K, V> multimap = LinkedListMultimap.create();
multimap.put(key1, foo);
multimap.put(key2, bar);
multimap.put(key1, baz);
... the iteration order for AbstractMultimap.keys()
is [key1, key2, key1]
,
and similarly for entries()
. Unlike LinkedHashMultimap
, the
iteration order is kept consistent between keys, entries and values. For
example, calling:
map.remove(key1, foo);
changes the entries iteration order to [key2=bar, key1=baz]
and the
key iteration order to [key2, key1]
. The entries()
iterator
returns mutable map entries, and replaceValues(K, java.lang.Iterable<? extends V>)
attempts to preserve
iteration order as much as possible.
The collections returned by AbstractMultimap.keySet()
and AbstractMultimap.asMap
iterate
through the keys in the order they were first added to the multimap.
Similarly, get(K)
, removeAll(java.lang.Object)
, and replaceValues(K, java.lang.Iterable<? extends V>)
return collections that iterate through the values in the order they were
added. The collections generated by entries()
, AbstractMultimap.keys()
, and
values()
iterate across the key-value mappings in the order they were
added to the multimap.
The values()
and entries()
methods both return a
List
, instead of the Collection
specified by the ListMultimap
interface.
The methods get(K)
, AbstractMultimap.keySet()
, AbstractMultimap.keys()
,
values()
, entries()
, and AbstractMultimap.asMap
return collections
that are views of the multimap. If the multimap is modified while an
iteration over any of those collections is in progress, except through the
iterator's methods, the results of the iteration are undefined.
Keys and values may be null. All optional multimap methods are supported, and all returned views are modifiable.
This class is not threadsafe when any concurrent operations update the
multimap. Concurrent read operations will work correctly. To allow concurrent
update operations, wrap your multimap with a call to Multimaps.synchronizedListMultimap(com.google.common.collect.ListMultimap<K, V>)
.
See the Guava User Guide article on
Multimap
.
Modifier and Type | Class and Description |
---|---|
private class |
LinkedListMultimap.DistinctKeyIterator
An
Iterator over distinct keys in key head order. |
private static class |
LinkedListMultimap.KeyList<K,V> |
private static class |
LinkedListMultimap.Node<K,V> |
private class |
LinkedListMultimap.NodeIterator
An
Iterator over all nodes. |
private class |
LinkedListMultimap.ValueForKeyIterator
A
ListIterator over values for a specified key. |
AbstractMultimap.Values
Modifier and Type | Field and Description |
---|---|
private LinkedListMultimap.Node<K,V> |
head |
private java.util.Map<K,LinkedListMultimap.KeyList<K,V>> |
keyToKeyList |
private int |
modCount |
private static long |
serialVersionUID |
private int |
size |
private LinkedListMultimap.Node<K,V> |
tail |
Modifier | Constructor and Description |
---|---|
(package private) |
LinkedListMultimap() |
private |
LinkedListMultimap(int expectedKeys) |
private |
LinkedListMultimap(Multimap<? extends K,? extends V> multimap) |
Modifier and Type | Method and Description |
---|---|
private LinkedListMultimap.Node<K,V> |
addNode(K key,
V value,
LinkedListMultimap.Node<K,V> nextSibling)
Adds a new node for the specified key-value pair before the specified
nextSibling element, or at the end of the list if nextSibling is null. |
private static void |
checkElement(java.lang.Object node)
Helper method for verifying that an iterator element is present.
|
void |
clear()
Removes all key-value pairs from the multimap, leaving it empty.
|
boolean |
containsKey(java.lang.Object key)
Returns
true if this multimap contains at least one key-value pair
with the key key . |
boolean |
containsValue(java.lang.Object value)
Returns
true if this multimap contains at least one key-value pair
with the value value . |
static <K,V> LinkedListMultimap<K,V> |
create()
Creates a new, empty
LinkedListMultimap with the default initial
capacity. |
static <K,V> LinkedListMultimap<K,V> |
create(int expectedKeys)
Constructs an empty
LinkedListMultimap with enough capacity to hold
the specified number of keys without rehashing. |
static <K,V> LinkedListMultimap<K,V> |
create(Multimap<? extends K,? extends V> multimap)
Constructs a
LinkedListMultimap with the same mappings as the
specified Multimap . |
(package private) java.util.Map<K,java.util.Collection<V>> |
createAsMap() |
(package private) java.util.List<java.util.Map.Entry<K,V>> |
createEntries() |
(package private) java.util.Set<K> |
createKeySet() |
(package private) java.util.List<V> |
createValues() |
java.util.List<java.util.Map.Entry<K,V>> |
entries()
Returns a view collection of all key-value pairs contained in this
multimap, as
Map.Entry instances. |
(package private) java.util.Iterator<java.util.Map.Entry<K,V>> |
entryIterator() |
java.util.List<V> |
get(K key)
Returns a view collection of the values associated with
key in this
multimap, if any. |
private java.util.List<V> |
getCopy(java.lang.Object key) |
boolean |
isEmpty()
Returns
true if this multimap contains no key-value pairs. |
boolean |
put(K key,
V value)
Stores a key-value pair in the multimap.
|
private void |
readObject(java.io.ObjectInputStream stream) |
java.util.List<V> |
removeAll(java.lang.Object key)
Removes all values associated with the key
key . |
private void |
removeAllNodes(java.lang.Object key)
Removes all nodes for the specified key.
|
private void |
removeNode(LinkedListMultimap.Node<K,V> node)
Removes the specified node from the linked list.
|
java.util.List<V> |
replaceValues(K key,
java.lang.Iterable<? extends V> values)
Stores a collection of values with the same key, replacing any existing
values for that key.
|
int |
size()
Returns the number of key-value pairs in this multimap.
|
java.util.List<V> |
values()
Returns a view collection containing the value from each key-value
pair contained in this multimap, without collapsing duplicates (so
values().size() == size() ). |
private void |
writeObject(java.io.ObjectOutputStream stream) |
asMap, containsEntry, createKeys, equals, hashCode, keys, keySet, putAll, putAll, remove, toString, valueIterator
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
asMap, equals
private transient LinkedListMultimap.Node<K,V> head
private transient LinkedListMultimap.Node<K,V> tail
private transient java.util.Map<K,LinkedListMultimap.KeyList<K,V>> keyToKeyList
private transient int size
private transient int modCount
@GwtIncompatible(value="java serialization not supported") private static final long serialVersionUID
LinkedListMultimap()
private LinkedListMultimap(int expectedKeys)
public static <K,V> LinkedListMultimap<K,V> create()
LinkedListMultimap
with the default initial
capacity.public static <K,V> LinkedListMultimap<K,V> create(int expectedKeys)
LinkedListMultimap
with enough capacity to hold
the specified number of keys without rehashing.expectedKeys
- the expected number of distinct keysjava.lang.IllegalArgumentException
- if expectedKeys
is negativepublic static <K,V> LinkedListMultimap<K,V> create(Multimap<? extends K,? extends V> multimap)
LinkedListMultimap
with the same mappings as the
specified Multimap
. The new multimap has the same
Multimap.entries()
iteration order as the input multimap.multimap
- the multimap whose contents are copied to this multimapprivate LinkedListMultimap.Node<K,V> addNode(@Nullable K key, @Nullable V value, @Nullable LinkedListMultimap.Node<K,V> nextSibling)
nextSibling
element, or at the end of the list if nextSibling
is null. Note: if nextSibling
is specified, it MUST be
for an node for the same key
!private void removeNode(LinkedListMultimap.Node<K,V> node)
Iterator
classes. See also removeAllNodes(Object)
.private void removeAllNodes(@Nullable java.lang.Object key)
private static void checkElement(@Nullable java.lang.Object node)
public int size()
Multimap
Note: this method does not return the number of distinct
keys in the multimap, which is given by keySet().size()
or
asMap().size()
. See the opening section of the Multimap
class documentation for clarification.
public boolean isEmpty()
Multimap
true
if this multimap contains no key-value pairs.
Equivalent to size() == 0
, but can in some cases be more efficient.public boolean containsKey(@Nullable java.lang.Object key)
Multimap
true
if this multimap contains at least one key-value pair
with the key key
.containsKey
in interface Multimap<K,V>
public boolean containsValue(@Nullable java.lang.Object value)
Multimap
true
if this multimap contains at least one key-value pair
with the value value
.containsValue
in interface Multimap<K,V>
containsValue
in class AbstractMultimap<K,V>
public java.util.List<V> replaceValues(@Nullable K key, java.lang.Iterable<? extends V> values)
If values
is empty, this is equivalent to
removeAll(key)
.
If any entries for the specified key
already exist in the
multimap, their values are changed in-place without affecting the iteration
order.
The returned list is immutable and implements
RandomAccess
.
replaceValues
in interface ListMultimap<K,V>
replaceValues
in interface Multimap<K,V>
replaceValues
in class AbstractMultimap<K,V>
private java.util.List<V> getCopy(@Nullable java.lang.Object key)
public java.util.List<V> removeAll(@Nullable java.lang.Object key)
key
.
Once this method returns, key
will not be mapped to any values,
so it will not appear in Multimap.keySet()
, Multimap.asMap()
, or any other
views.
Because the values for a given key may have duplicates and follow the
insertion ordering, this method returns a List
, instead of the
Collection
specified in the Multimap
interface.
The returned list is immutable and implements
RandomAccess
.
public void clear()
Multimap
public java.util.List<V> get(@Nullable K key)
key
in this
multimap, if any. Note that when containsKey(key)
is false, this
returns an empty collection, not null
.
Changes to the returned collection will update the underlying multimap, and vice versa.
Because the values for a given key may have duplicates and follow the
insertion ordering, this method returns a List
, instead of the
Collection
specified in the Multimap
interface.
If the multimap is modified while an iteration over the list is in
progress (except through the iterator's own add
, set
or
remove
operations) the results of the iteration are undefined.
The returned list is not serializable and does not have random access.
java.util.Set<K> createKeySet()
createKeySet
in class AbstractMultimap<K,V>
public java.util.List<V> values()
values().size() == size()
).
Changes to the returned collection will update the underlying multimap, and vice versa. However, adding to the returned collection is not possible.
The iterator generated by the returned collection traverses the values
in the order they were added to the multimap. Because the values may have
duplicates and follow the insertion ordering, this method returns a List
, instead of the Collection
specified in the ListMultimap
interface.
java.util.List<V> createValues()
createValues
in class AbstractMultimap<K,V>
public java.util.List<java.util.Map.Entry<K,V>> entries()
Map.Entry
instances.
Changes to the returned collection or the entries it contains will update the underlying multimap, and vice versa. However, adding to the returned collection is not possible.
The iterator generated by the returned collection traverses the entries
in the order they were added to the multimap. Because the entries may have
duplicates and follow the insertion ordering, this method returns a List
, instead of the Collection
specified in the ListMultimap
interface.
An entry's Map.Entry.getKey()
method always returns the same key,
regardless of what happens subsequently. As long as the corresponding
key-value mapping is not removed from the multimap, Map.Entry.getValue()
returns the value from the multimap, which may change over time, and Map.Entry.setValue(V)
modifies that value. Removing the mapping from the
multimap does not alter the value returned by getValue()
, though a
subsequent setValue()
call won't update the multimap but will lead
to a revised value being returned by getValue()
.
java.util.List<java.util.Map.Entry<K,V>> createEntries()
createEntries
in class AbstractMultimap<K,V>
java.util.Iterator<java.util.Map.Entry<K,V>> entryIterator()
entryIterator
in class AbstractMultimap<K,V>
java.util.Map<K,java.util.Collection<V>> createAsMap()
createAsMap
in class AbstractMultimap<K,V>
@GwtIncompatible(value="java.io.ObjectOutputStream") private void writeObject(java.io.ObjectOutputStream stream) throws java.io.IOException
java.io.IOException
@GwtIncompatible(value="java.io.ObjectInputStream") private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException, java.lang.ClassNotFoundException
java.io.IOException
java.lang.ClassNotFoundException