Add keywords
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@209673 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0fdd5982c3
commit
c9a30909de
|
@ -1,407 +1,407 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2005 The Apache Software Foundation
|
* Copyright 2001-2005 The Apache Software Foundation
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.collections.map;
|
package org.apache.commons.collections.map;
|
||||||
|
|
||||||
import java.util.AbstractCollection;
|
import java.util.AbstractCollection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.collections.Factory;
|
import org.apache.commons.collections.Factory;
|
||||||
import org.apache.commons.collections.MultiMap;
|
import org.apache.commons.collections.MultiMap;
|
||||||
import org.apache.commons.collections.iterators.EmptyIterator;
|
import org.apache.commons.collections.iterators.EmptyIterator;
|
||||||
import org.apache.commons.collections.iterators.IteratorChain;
|
import org.apache.commons.collections.iterators.IteratorChain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MultiValueMap decorates another map, allowing it to have
|
* A MultiValueMap decorates another map, allowing it to have
|
||||||
* more than one value for a key.
|
* more than one value for a key.
|
||||||
* <p>
|
* <p>
|
||||||
* A <code>MultiMap</code> is a Map with slightly different semantics.
|
* A <code>MultiMap</code> is a Map with slightly different semantics.
|
||||||
* Putting a value into the map will add the value to a Collection at that key.
|
* Putting a value into the map will add the value to a Collection at that key.
|
||||||
* Getting a value will return a Collection, holding all the values put to that key.
|
* Getting a value will return a Collection, holding all the values put to that key.
|
||||||
* <p>
|
* <p>
|
||||||
* This implementation is a decorator, allowing any Map implementation
|
* This implementation is a decorator, allowing any Map implementation
|
||||||
* to be used as the base.
|
* to be used as the base.
|
||||||
* <p>
|
* <p>
|
||||||
* In addition, this implementation allows the type of collection used
|
* In addition, this implementation allows the type of collection used
|
||||||
* for the values to be controlled. By default, an <code>ArrayList</code>
|
* for the values to be controlled. By default, an <code>ArrayList</code>
|
||||||
* is used, however a <code>Class</code> to instantiate may be specified,
|
* is used, however a <code>Class</code> to instantiate may be specified,
|
||||||
* or a factory that returns a <code>Collection</code> instance.
|
* or a factory that returns a <code>Collection</code> instance.
|
||||||
*
|
*
|
||||||
* @author James Carman
|
* @author James Carman
|
||||||
* @author Christopher Berry
|
* @author Christopher Berry
|
||||||
* @author James Strachan
|
* @author James Strachan
|
||||||
* @author Steve Downey
|
* @author Steve Downey
|
||||||
* @author Stephen Colebourne
|
* @author Stephen Colebourne
|
||||||
* @author Julien Buret
|
* @author Julien Buret
|
||||||
* @author Serhiy Yevtushenko
|
* @author Serhiy Yevtushenko
|
||||||
* @version $Revision: $ $Date: $
|
* @version $Revision$ $Date$
|
||||||
* @since Commons Collections 3.2
|
* @since Commons Collections 3.2
|
||||||
*/
|
*/
|
||||||
public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
|
public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
|
||||||
|
|
||||||
/** The factory for creating value collections. */
|
/** The factory for creating value collections. */
|
||||||
private final Factory collectionFactory;
|
private final Factory collectionFactory;
|
||||||
/** The cached values. */
|
/** The cached values. */
|
||||||
private transient Collection values;
|
private transient Collection values;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a map which wraps the given map and
|
* Creates a map which wraps the given map and
|
||||||
* maps keys to ArrayLists.
|
* maps keys to ArrayLists.
|
||||||
*
|
*
|
||||||
* @param map the map to wrap
|
* @param map the map to wrap
|
||||||
*/
|
*/
|
||||||
public static MultiValueMap decorate(Map map) {
|
public static MultiValueMap decorate(Map map) {
|
||||||
return new MultiValueMap(map, new ReflectionFactory(ArrayList.class));
|
return new MultiValueMap(map, new ReflectionFactory(ArrayList.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a map which decorates the given <code>map</code> and
|
* Creates a map which decorates the given <code>map</code> and
|
||||||
* maps keys to collections of type <code>collectionClass</code>.
|
* maps keys to collections of type <code>collectionClass</code>.
|
||||||
*
|
*
|
||||||
* @param map the map to wrap
|
* @param map the map to wrap
|
||||||
* @param collectionClass the type of the collection class
|
* @param collectionClass the type of the collection class
|
||||||
*/
|
*/
|
||||||
public static MultiValueMap decorate(Map map, Class collectionClass) {
|
public static MultiValueMap decorate(Map map, Class collectionClass) {
|
||||||
return new MultiValueMap(map, new ReflectionFactory(collectionClass));
|
return new MultiValueMap(map, new ReflectionFactory(collectionClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a map which decorates the given <code>map</code> and
|
* Creates a map which decorates the given <code>map</code> and
|
||||||
* creates the value collections using the supplied <code>collectionFactory</code>.
|
* creates the value collections using the supplied <code>collectionFactory</code>.
|
||||||
*
|
*
|
||||||
* @param map the map to decorate
|
* @param map the map to decorate
|
||||||
* @param collectionFactory the collection factory (must return a Collection object).
|
* @param collectionFactory the collection factory (must return a Collection object).
|
||||||
*/
|
*/
|
||||||
public static MultiValueMap decorate(Map map, Factory collectionFactory) {
|
public static MultiValueMap decorate(Map map, Factory collectionFactory) {
|
||||||
return new MultiValueMap(map, collectionFactory);
|
return new MultiValueMap(map, collectionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Creates a MultiValueMap based on a <code>HashMap</code> and
|
* Creates a MultiValueMap based on a <code>HashMap</code> and
|
||||||
* storing the multiple values in an <code>ArrayList</code>.
|
* storing the multiple values in an <code>ArrayList</code>.
|
||||||
*/
|
*/
|
||||||
public MultiValueMap() {
|
public MultiValueMap() {
|
||||||
this(new HashMap(), new ReflectionFactory(ArrayList.class));
|
this(new HashMap(), new ReflectionFactory(ArrayList.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a MultiValueMap which decorates the given <code>map</code> and
|
* Creates a MultiValueMap which decorates the given <code>map</code> and
|
||||||
* creates the value collections using the supplied <code>collectionFactory</code>.
|
* creates the value collections using the supplied <code>collectionFactory</code>.
|
||||||
*
|
*
|
||||||
* @param map the map to decorate
|
* @param map the map to decorate
|
||||||
* @param collectionFactory the collection factory which must return a Collection instance
|
* @param collectionFactory the collection factory which must return a Collection instance
|
||||||
*/
|
*/
|
||||||
protected MultiValueMap(Map map, Factory collectionFactory) {
|
protected MultiValueMap(Map map, Factory collectionFactory) {
|
||||||
super(map);
|
super(map);
|
||||||
if (collectionFactory == null) {
|
if (collectionFactory == null) {
|
||||||
throw new IllegalArgumentException("The factory must not be null");
|
throw new IllegalArgumentException("The factory must not be null");
|
||||||
}
|
}
|
||||||
this.collectionFactory = collectionFactory;
|
this.collectionFactory = collectionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Clear the map.
|
* Clear the map.
|
||||||
*/
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
// If you believe that you have GC issues here, try uncommenting this code
|
// If you believe that you have GC issues here, try uncommenting this code
|
||||||
// Set pairs = getMap().entrySet();
|
// Set pairs = getMap().entrySet();
|
||||||
// Iterator pairsIterator = pairs.iterator();
|
// Iterator pairsIterator = pairs.iterator();
|
||||||
// while (pairsIterator.hasNext()) {
|
// while (pairsIterator.hasNext()) {
|
||||||
// Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
|
// Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
|
||||||
// Collection coll = (Collection) keyValuePair.getValue();
|
// Collection coll = (Collection) keyValuePair.getValue();
|
||||||
// coll.clear();
|
// coll.clear();
|
||||||
// }
|
// }
|
||||||
getMap().clear();
|
getMap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a specific value from map.
|
* Removes a specific value from map.
|
||||||
* <p>
|
* <p>
|
||||||
* The item is removed from the collection mapped to the specified key.
|
* The item is removed from the collection mapped to the specified key.
|
||||||
* Other values attached to that key are unaffected.
|
* Other values attached to that key are unaffected.
|
||||||
* <p>
|
* <p>
|
||||||
* If the last value for a key is removed, <code>null</code> will be returned
|
* If the last value for a key is removed, <code>null</code> will be returned
|
||||||
* from a subsequant <code>get(key)</code>.
|
* from a subsequant <code>get(key)</code>.
|
||||||
*
|
*
|
||||||
* @param key the key to remove from
|
* @param key the key to remove from
|
||||||
* @param value the value to remove
|
* @param value the value to remove
|
||||||
* @return the value removed (which was passed in), null if nothing removed
|
* @return the value removed (which was passed in), null if nothing removed
|
||||||
*/
|
*/
|
||||||
public Object remove(Object key, Object value) {
|
public Object remove(Object key, Object value) {
|
||||||
Collection valuesForKey = getCollection(key);
|
Collection valuesForKey = getCollection(key);
|
||||||
if (valuesForKey == null) {
|
if (valuesForKey == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean removed = valuesForKey.remove(value);
|
boolean removed = valuesForKey.remove(value);
|
||||||
if (removed == false) {
|
if (removed == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (valuesForKey.isEmpty()) {
|
if (valuesForKey.isEmpty()) {
|
||||||
remove(key);
|
remove(key);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the map contains the value specified.
|
* Checks whether the map contains the value specified.
|
||||||
* <p>
|
* <p>
|
||||||
* This checks all collections against all keys for the value, and thus could be slow.
|
* This checks all collections against all keys for the value, and thus could be slow.
|
||||||
*
|
*
|
||||||
* @param value the value to search for
|
* @param value the value to search for
|
||||||
* @return true if the map contains the value
|
* @return true if the map contains the value
|
||||||
*/
|
*/
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
Set pairs = getMap().entrySet();
|
Set pairs = getMap().entrySet();
|
||||||
if (pairs == null) {
|
if (pairs == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Iterator pairsIterator = pairs.iterator();
|
Iterator pairsIterator = pairs.iterator();
|
||||||
while (pairsIterator.hasNext()) {
|
while (pairsIterator.hasNext()) {
|
||||||
Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
|
Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
|
||||||
Collection coll = (Collection) keyValuePair.getValue();
|
Collection coll = (Collection) keyValuePair.getValue();
|
||||||
if (coll.contains(value)) {
|
if (coll.contains(value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the value to the collection associated with the specified key.
|
* Adds the value to the collection associated with the specified key.
|
||||||
* <p>
|
* <p>
|
||||||
* Unlike a normal <code>Map</code> the previous value is not replaced.
|
* Unlike a normal <code>Map</code> the previous value is not replaced.
|
||||||
* Instead the new value is added to the collection stored against the key.
|
* Instead the new value is added to the collection stored against the key.
|
||||||
*
|
*
|
||||||
* @param key the key to store against
|
* @param key the key to store against
|
||||||
* @param value the value to add to the collection at the key
|
* @param value the value to add to the collection at the key
|
||||||
* @return the value added if the map changed and null if the map did not change
|
* @return the value added if the map changed and null if the map did not change
|
||||||
*/
|
*/
|
||||||
public Object put(Object key, Object value) {
|
public Object put(Object key, Object value) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
Collection coll = getCollection(key);
|
Collection coll = getCollection(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
coll = createCollection(1);
|
coll = createCollection(1);
|
||||||
result = coll.add(value);
|
result = coll.add(value);
|
||||||
if (coll.size() > 0) {
|
if (coll.size() > 0) {
|
||||||
// only add if non-zero size to maintain class state
|
// only add if non-zero size to maintain class state
|
||||||
getMap().put(key, coll);
|
getMap().put(key, coll);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = coll.add(value);
|
result = coll.add(value);
|
||||||
}
|
}
|
||||||
return (result ? value : null);
|
return (result ? value : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a collection containing all the values in the map.
|
* Gets a collection containing all the values in the map.
|
||||||
* <p>
|
* <p>
|
||||||
* This returns a collection containing the combination of values from all keys.
|
* This returns a collection containing the combination of values from all keys.
|
||||||
*
|
*
|
||||||
* @return a collection view of the values contained in this map
|
* @return a collection view of the values contained in this map
|
||||||
*/
|
*/
|
||||||
public Collection values() {
|
public Collection values() {
|
||||||
Collection vs = values;
|
Collection vs = values;
|
||||||
return (vs != null ? vs : (values = new Values()));
|
return (vs != null ? vs : (values = new Values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the collection at the specified key contains the value.
|
* Checks whether the collection at the specified key contains the value.
|
||||||
*
|
*
|
||||||
* @param value the value to search for
|
* @param value the value to search for
|
||||||
* @return true if the map contains the value
|
* @return true if the map contains the value
|
||||||
*/
|
*/
|
||||||
public boolean containsValue(Object key, Object value) {
|
public boolean containsValue(Object key, Object value) {
|
||||||
Collection coll = getCollection(key);
|
Collection coll = getCollection(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return coll.contains(value);
|
return coll.contains(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the collection mapped to the specified key.
|
* Gets the collection mapped to the specified key.
|
||||||
* This method is a convenience method to typecast the result of <code>get(key)</code>.
|
* This method is a convenience method to typecast the result of <code>get(key)</code>.
|
||||||
*
|
*
|
||||||
* @param key the key to retrieve
|
* @param key the key to retrieve
|
||||||
* @return the collection mapped to the key, null if no mapping
|
* @return the collection mapped to the key, null if no mapping
|
||||||
*/
|
*/
|
||||||
public Collection getCollection(Object key) {
|
public Collection getCollection(Object key) {
|
||||||
return (Collection) getMap().get(key);
|
return (Collection) getMap().get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the size of the collection mapped to the specified key.
|
* Gets the size of the collection mapped to the specified key.
|
||||||
*
|
*
|
||||||
* @param key the key to get size for
|
* @param key the key to get size for
|
||||||
* @return the size of the collection at the key, zero if key not in map
|
* @return the size of the collection at the key, zero if key not in map
|
||||||
*/
|
*/
|
||||||
public int size(Object key) {
|
public int size(Object key) {
|
||||||
Collection coll = getCollection(key);
|
Collection coll = getCollection(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return coll.size();
|
return coll.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a collection of values to the collection associated with
|
* Adds a collection of values to the collection associated with
|
||||||
* the specified key.
|
* the specified key.
|
||||||
*
|
*
|
||||||
* @param key the key to store against
|
* @param key the key to store against
|
||||||
* @param values the values to add to the collection at the key, null ignored
|
* @param values the values to add to the collection at the key, null ignored
|
||||||
* @return true if this map changed
|
* @return true if this map changed
|
||||||
*/
|
*/
|
||||||
public boolean putAll(Object key, Collection values) {
|
public boolean putAll(Object key, Collection values) {
|
||||||
if (values == null || values.size() == 0) {
|
if (values == null || values.size() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Collection coll = getCollection(key);
|
Collection coll = getCollection(key);
|
||||||
if (coll == null) {
|
if (coll == null) {
|
||||||
coll = createCollection(values.size());
|
coll = createCollection(values.size());
|
||||||
boolean result = coll.addAll(values);
|
boolean result = coll.addAll(values);
|
||||||
if (coll.size() > 0) {
|
if (coll.size() > 0) {
|
||||||
// only add if non-zero size to maintain class state
|
// only add if non-zero size to maintain class state
|
||||||
getMap().put(key, coll);
|
getMap().put(key, coll);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return coll.addAll(values);
|
return coll.addAll(values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an iterator for the collection mapped to the specified key.
|
* Gets an iterator for the collection mapped to the specified key.
|
||||||
*
|
*
|
||||||
* @param key the key to get an iterator for
|
* @param key the key to get an iterator for
|
||||||
* @return the iterator of the collection at the key, empty iterator if key not in map
|
* @return the iterator of the collection at the key, empty iterator if key not in map
|
||||||
*/
|
*/
|
||||||
public Iterator iterator(Object key) {
|
public Iterator iterator(Object key) {
|
||||||
if (!containsKey(key)) {
|
if (!containsKey(key)) {
|
||||||
return EmptyIterator.INSTANCE;
|
return EmptyIterator.INSTANCE;
|
||||||
} else {
|
} else {
|
||||||
return new ValuesIterator(key);
|
return new ValuesIterator(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the total size of the map by counting all the values.
|
* Gets the total size of the map by counting all the values.
|
||||||
*
|
*
|
||||||
* @return the total size of the map counting all values
|
* @return the total size of the map counting all values
|
||||||
*/
|
*/
|
||||||
public int totalSize() {
|
public int totalSize() {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
Collection values = getMap().values();
|
Collection values = getMap().values();
|
||||||
for (Iterator it = values.iterator(); it.hasNext();) {
|
for (Iterator it = values.iterator(); it.hasNext();) {
|
||||||
Collection coll = (Collection) it.next();
|
Collection coll = (Collection) it.next();
|
||||||
total += coll.size();
|
total += coll.size();
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the map value Collection container
|
* Creates a new instance of the map value Collection container
|
||||||
* using the factory.
|
* using the factory.
|
||||||
* <p>
|
* <p>
|
||||||
* This method can be overridden to perform your own processing
|
* This method can be overridden to perform your own processing
|
||||||
* instead of using the factory.
|
* instead of using the factory.
|
||||||
*
|
*
|
||||||
* @param size the collection size that is about to be added
|
* @param size the collection size that is about to be added
|
||||||
* @return the new collection
|
* @return the new collection
|
||||||
*/
|
*/
|
||||||
protected Collection createCollection(int size) {
|
protected Collection createCollection(int size) {
|
||||||
return (Collection) collectionFactory.create();
|
return (Collection) collectionFactory.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Inner class that provides the values view.
|
* Inner class that provides the values view.
|
||||||
*/
|
*/
|
||||||
private class Values extends AbstractCollection {
|
private class Values extends AbstractCollection {
|
||||||
public Iterator iterator() {
|
public Iterator iterator() {
|
||||||
final IteratorChain chain = new IteratorChain();
|
final IteratorChain chain = new IteratorChain();
|
||||||
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
for (Iterator it = keySet().iterator(); it.hasNext();) {
|
||||||
chain.addIterator(new ValuesIterator(it.next()));
|
chain.addIterator(new ValuesIterator(it.next()));
|
||||||
}
|
}
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return totalSize();
|
return totalSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
MultiValueMap.this.clear();
|
MultiValueMap.this.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class that provides the values iterator.
|
* Inner class that provides the values iterator.
|
||||||
*/
|
*/
|
||||||
private class ValuesIterator implements Iterator {
|
private class ValuesIterator implements Iterator {
|
||||||
private final Object key;
|
private final Object key;
|
||||||
private final Collection values;
|
private final Collection values;
|
||||||
private final Iterator iterator;
|
private final Iterator iterator;
|
||||||
|
|
||||||
public ValuesIterator(Object key) {
|
public ValuesIterator(Object key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.values = getCollection(key);
|
this.values = getCollection(key);
|
||||||
this.iterator = values.iterator();
|
this.iterator = values.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
MultiValueMap.this.remove(key);
|
MultiValueMap.this.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return iterator.hasNext();
|
return iterator.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public Object next() {
|
||||||
return iterator.next();
|
return iterator.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class that provides a simple reflection factory.
|
* Inner class that provides a simple reflection factory.
|
||||||
*/
|
*/
|
||||||
private static class ReflectionFactory implements Factory {
|
private static class ReflectionFactory implements Factory {
|
||||||
private final Class clazz;
|
private final Class clazz;
|
||||||
|
|
||||||
public ReflectionFactory(Class clazz) {
|
public ReflectionFactory(Class clazz) {
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object create() {
|
public Object create() {
|
||||||
try {
|
try {
|
||||||
return clazz.newInstance();
|
return clazz.newInstance();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException("Cannot instantiate class: " + clazz, ex);
|
throw new RuntimeException("Cannot instantiate class: " + clazz, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue