Generified LazyMap
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/branches/collections_jdk5_branch@571381 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
683959a471
commit
b2939e2c47
|
@ -64,10 +64,10 @@ public class FactoryUtils {
|
|||
* This could be useful during testing as a placeholder.
|
||||
*
|
||||
* @see org.apache.commons.collections.functors.ConstantFactory
|
||||
*
|
||||
* @param <T> the "type" of null object the factory should return.
|
||||
* @return the factory
|
||||
*/
|
||||
public static Factory nullFactory() {
|
||||
public static <T> Factory<T> nullFactory() {
|
||||
return ConstantFactory.NULL_INSTANCE;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,15 +62,15 @@ import org.apache.commons.collections.functors.FactoryTransformer;
|
|||
* @author Stephen Colebourne
|
||||
* @author Paul Jack
|
||||
*/
|
||||
public class LazyMap
|
||||
extends AbstractMapDecorator
|
||||
implements Map, Serializable {
|
||||
public class LazyMap<K,V>
|
||||
extends AbstractMapDecorator<K,V>
|
||||
implements Map<K,V>, Serializable {
|
||||
|
||||
/** Serialization version */
|
||||
private static final long serialVersionUID = 7990956402564206740L;
|
||||
|
||||
/** The factory to use to construct elements */
|
||||
protected final Transformer factory;
|
||||
protected final Transformer<? super K, ? extends V> factory;
|
||||
|
||||
/**
|
||||
* Factory method to create a lazily instantiated map.
|
||||
|
@ -78,9 +78,11 @@ public class LazyMap
|
|||
* @param map the map to decorate, must not be null
|
||||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
* @deprecated use {@link #getLazyMap(Map, Factory)} instead.
|
||||
*/
|
||||
public static Map decorate(Map map, Factory factory) {
|
||||
return new LazyMap(map, factory);
|
||||
@Deprecated
|
||||
public static <K,V> Map<K,V> decorate(Map<K,V> map, Factory<? extends V> factory) {
|
||||
return getLazyMap(map, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,10 +92,34 @@ public class LazyMap
|
|||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
*/
|
||||
public static Map decorate(Map map, Transformer factory) {
|
||||
return new LazyMap(map, factory);
|
||||
public static <K, V> LazyMap<K, V> getLazyMap(Map<K, V> map, Factory< ? extends V> factory) {
|
||||
return new LazyMap<K,V>(map, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a lazily instantiated map.
|
||||
*
|
||||
* @param map the map to decorate, must not be null
|
||||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
* @deprecated use {@link #getLazyMap(Map, Transformer)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static <K,V> Map<K,V> decorate(Map<K,V> map, Transformer<? super K, ? extends V> factory) {
|
||||
return getLazyMap(map, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a lazily instantiated map.
|
||||
*
|
||||
* @param map the map to decorate, must not be null
|
||||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
*/
|
||||
public static <V, K> LazyMap<K, V> getLazyMap(Map<K, V> map, Transformer<? super K, ? extends V> factory) {
|
||||
return new LazyMap<K,V>(map, factory);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Constructor that wraps (not copies).
|
||||
|
@ -102,7 +128,7 @@ public class LazyMap
|
|||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
*/
|
||||
protected LazyMap(Map map, Factory factory) {
|
||||
protected LazyMap(Map<K,V> map, Factory<? extends V> factory) {
|
||||
super(map);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Factory must not be null");
|
||||
|
@ -117,7 +143,7 @@ public class LazyMap
|
|||
* @param factory the factory to use, must not be null
|
||||
* @throws IllegalArgumentException if map or factory is null
|
||||
*/
|
||||
protected LazyMap(Map map, Transformer factory) {
|
||||
protected LazyMap(Map<K,V> map, Transformer<? super K, ? extends V> factory) {
|
||||
super(map);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Factory must not be null");
|
||||
|
@ -146,22 +172,36 @@ public class LazyMap
|
|||
* @throws ClassNotFoundException
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
map = (Map) in.readObject();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
public Object get(Object key) {
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
// create value for key if key is not currently in the map
|
||||
if (map.containsKey(key) == false) {
|
||||
Object value = factory.transform(key);
|
||||
map.put(key, value);
|
||||
K castKey = cast(key);
|
||||
V value = factory.transform(castKey);
|
||||
map.put(castKey, value);
|
||||
return value;
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method just to cast {@link Object}s to K where necessary. This is done to ensure that the SuppressWarnings does not
|
||||
* cover other stuff that it shouldn't
|
||||
* @param key .
|
||||
* @return the cast key.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private K cast(Object key) {
|
||||
return (K) key;
|
||||
}
|
||||
|
||||
// no need to wrap keySet, entrySet or values as they are views of
|
||||
// existing map entries - you can't do a map-style get on them.
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ public abstract class AbstractTestMap extends AbstractTestObject {
|
|||
*
|
||||
* @return the map to be tested
|
||||
*/
|
||||
public abstract Map makeEmptyMap();
|
||||
public abstract <K,V> Map<K,V> makeEmptyMap();
|
||||
|
||||
/**
|
||||
* Return a new, populated map. The mappings in the map should match the
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
*/
|
||||
package org.apache.commons.collections.map;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
/**
|
||||
* Entry point for tests.
|
||||
|
@ -27,51 +29,38 @@ import junit.framework.TestSuite;
|
|||
* @version $Revision$ $Date$
|
||||
*
|
||||
* @author Stephen Colebourne
|
||||
* @author Stephen Kestle
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
TestCaseInsensitiveMap.class,
|
||||
TestCompositeMap.class,
|
||||
TestDefaultedMap.class,
|
||||
TestFlat3Map.class,
|
||||
TestHashedMap.class,
|
||||
TestIdentityMap.class,
|
||||
TestLinkedMap.class,
|
||||
TestLRUMap.class,
|
||||
TestMultiKeyMap.class,
|
||||
TestReferenceMap.class,
|
||||
TestReferenceIdentityMap.class,
|
||||
TestStaticBucketMap.class,
|
||||
TestSingletonMap.class,
|
||||
|
||||
TestFixedSizeMap.class,
|
||||
TestFixedSizeSortedMap.class,
|
||||
TestLazyMap.class,
|
||||
TestLazySortedMap.class,
|
||||
TestListOrderedMap.class,
|
||||
TestListOrderedMap2.class,
|
||||
TestMultiValueMap.class,
|
||||
TestPredicatedMap.class,
|
||||
TestPredicatedSortedMap.class,
|
||||
TestTransformedMap.class,
|
||||
TestTransformedSortedMap.class,
|
||||
TestUnmodifiableMap.class,
|
||||
TestUnmodifiableOrderedMap.class,
|
||||
TestUnmodifiableSortedMap.class
|
||||
})
|
||||
public class TestAll extends TestCase {
|
||||
|
||||
public TestAll(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
String[] testCaseName = { TestAll.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTest(TestCaseInsensitiveMap.suite());
|
||||
suite.addTest(TestCompositeMap.suite());
|
||||
suite.addTest(TestDefaultedMap.suite());
|
||||
suite.addTest(TestFlat3Map.suite());
|
||||
suite.addTest(TestHashedMap.suite());
|
||||
suite.addTest(TestIdentityMap.suite());
|
||||
suite.addTest(TestLinkedMap.suite());
|
||||
suite.addTest(TestLRUMap.suite());
|
||||
suite.addTest(TestMultiKeyMap.suite());
|
||||
suite.addTest(TestReferenceMap.suite());
|
||||
suite.addTest(TestReferenceIdentityMap.suite());
|
||||
suite.addTest(TestStaticBucketMap.suite());
|
||||
suite.addTest(TestSingletonMap.suite());
|
||||
|
||||
suite.addTest(TestFixedSizeMap.suite());
|
||||
suite.addTest(TestFixedSizeSortedMap.suite());
|
||||
suite.addTest(TestLazyMap.suite());
|
||||
suite.addTest(TestLazySortedMap.suite());
|
||||
suite.addTest(TestListOrderedMap.suite());
|
||||
suite.addTest(TestListOrderedMap2.suite());
|
||||
suite.addTest(TestMultiValueMap.suite());
|
||||
suite.addTest(TestPredicatedMap.suite());
|
||||
suite.addTest(TestPredicatedSortedMap.suite());
|
||||
suite.addTest(TestTransformedMap.suite());
|
||||
suite.addTest(TestTransformedSortedMap.suite());
|
||||
suite.addTest(TestUnmodifiableMap.suite());
|
||||
suite.addTest(TestUnmodifiableOrderedMap.suite());
|
||||
suite.addTest(TestUnmodifiableSortedMap.suite());
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
*/
|
||||
package org.apache.commons.collections.map;
|
||||
|
||||
import static org.apache.commons.collections.map.LazyMap.getLazyMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.commons.collections.Factory;
|
||||
import org.apache.commons.collections.FactoryUtils;
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Extension of {@link TestMap} for exercising the
|
||||
|
@ -36,55 +37,64 @@ import org.apache.commons.collections.FactoryUtils;
|
|||
*/
|
||||
public class TestLazyMap extends AbstractTestMap {
|
||||
|
||||
protected static final Factory oneFactory = FactoryUtils.constantFactory("One");
|
||||
protected static final Factory nullFactory = FactoryUtils.nullFactory();
|
||||
private static final Factory<Integer> oneFactory = FactoryUtils.constantFactory(1);
|
||||
private static final Factory<Object> nullFactory = FactoryUtils.nullFactory();
|
||||
|
||||
public TestLazyMap(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return new TestSuite(TestLazyMap.class);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
String[] testCaseName = { TestLazyMap.class.getName()};
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
protected Map decorateMap(Map map, Factory factory) {
|
||||
return LazyMap.decorate(map, factory);
|
||||
}
|
||||
|
||||
public Map makeEmptyMap() {
|
||||
return decorateMap(new HashMap(), nullFactory);
|
||||
}
|
||||
|
||||
protected Map makeTestMap(Factory factory) {
|
||||
return decorateMap(new HashMap(), factory);
|
||||
@Override
|
||||
public <K,V> Map<K,V> makeEmptyMap() {
|
||||
return getLazyMap(new HashMap<K,V>(), FactoryUtils.<V>nullFactory());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public void testMapGet() {
|
||||
Map map = makeTestMap(oneFactory);
|
||||
assertEquals(0, map.size());
|
||||
String s1 = (String) map.get("Five");
|
||||
assertEquals("One", s1);
|
||||
assertEquals(1, map.size());
|
||||
String s2 = (String) map.get(new String(new char[] {'F','i','v','e'}));
|
||||
assertEquals("One", s2);
|
||||
assertEquals(1, map.size());
|
||||
assertSame(s1, s2);
|
||||
//TODO eliminate need for this via superclass - see svn history.
|
||||
}
|
||||
|
||||
map = makeTestMap(nullFactory);
|
||||
@Test
|
||||
public void mapGetWithFactory() {
|
||||
Map<Integer, Number> map = getLazyMap(new HashMap<Integer,Number>(), oneFactory);
|
||||
assertEquals(0, map.size());
|
||||
Number i1 = map.get("Five");
|
||||
assertEquals(1, i1);
|
||||
assertEquals(1, map.size());
|
||||
Number i2 = map.get(new String(new char[] {'F','i','v','e'}));
|
||||
assertEquals(1, i2);
|
||||
assertEquals(1, map.size());
|
||||
assertSame(i1, i2);
|
||||
|
||||
map = getLazyMap(new HashMap<Integer,Number>(), FactoryUtils.<Long>nullFactory());
|
||||
Object o = map.get("Five");
|
||||
assertEquals(null,o);
|
||||
assertEquals(1, map.size());
|
||||
|
||||
}
|
||||
|
||||
public String getCompatibilityVersion() {
|
||||
@Test
|
||||
public void mapGetWithTransformer() {
|
||||
Transformer<Number, Integer> intConverter = new Transformer<Number, Integer>(){
|
||||
public Integer transform(Number input) {
|
||||
return input.intValue();
|
||||
}
|
||||
};
|
||||
Map<Long, Number> map = getLazyMap(new HashMap<Long,Number>(), intConverter );
|
||||
assertEquals(0, map.size());
|
||||
Number i1 = map.get(123L);
|
||||
assertEquals(123, i1);
|
||||
assertEquals(1, map.size());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getCompatibilityVersion() {
|
||||
return "3.1";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue