Решение от @ tendayi-mawushe не работает для меня с примитивными типами (например, InstantiationException Integer
), вот одна реализация, которая работает с Integer, Double, Float. Я часто использую карты с этим и добавлены статические конструкторы для conveninence
import java.util.HashMap;
import java.util.Map;
/** Simulate the behaviour of Python's defaultdict */
public class DefaultHashMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
private final Class<V> cls;
private final Number defaultValue;
@SuppressWarnings({ "rawtypes", "unchecked" })
public DefaultHashMap(Class factory) {
this.cls = factory;
this.defaultValue = null;
}
public DefaultHashMap(Number defaultValue) {
this.cls = null;
this.defaultValue = defaultValue;
}
@SuppressWarnings("unchecked")
@Override
public V get(Object key) {
V value = super.get(key);
if (value == null) {
if (defaultValue == null) {
try {
value = cls.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
} else {
value = (V) defaultValue;
}
this.put((K) key, value);
}
return value;
}
public static <T> Map<T, Integer> intDefaultMap() {
return new DefaultHashMap<T, Integer>(0);
}
public static <T> Map<T, Double> doubleDefaultMap() {
return new DefaultHashMap<T, Double>(0d);
}
public static <T> Map<T, Float> floatDefaultMap() {
return new DefaultHashMap<T, Float>(0f);
}
public static <T> Map<T, String> stringDefaultMap() {
return new DefaultHashMap<T, String>(String.class);
}
}
И тест, хорошие манеры:
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Test;
public class DefaultHashMapTest {
@Test
public void test() {
Map<String, List<String>> dm = new DefaultHashMap<String, List<String>>(
ArrayList.class);
dm.get("nokey").add("one");
dm.get("nokey").add("two");
assertEquals(2, dm.get("nokey").size());
assertEquals(0, dm.get("nokey2").size());
}
@Test
public void testInt() {
Map<String, Integer> dm = DefaultHashMap.intDefaultMap();
assertEquals(new Integer(0), dm.get("nokey"));
assertEquals(new Integer(0), dm.get("nokey2"));
dm.put("nokey", 3);
assertEquals(new Integer(0), dm.get("nokey2"));
dm.put("nokey3", 3);
assertEquals(new Integer(3), dm.get("nokey3"));
}
@Test
public void testString() {
Map<String, String> dm = DefaultHashMap.stringDefaultMap();
assertEquals("", dm.get("nokey"));
dm.put("nokey1", "mykey");
assertEquals("mykey", dm.get("nokey1"));
}
}
Вместо использования 'класса' вы также можете попробовать пройти мимо Guava 'Поставщик' - см. Http://docs.guava-libraries.googlecode.com/git-history/v10.0/javadoc/com/google/common/base/Supplier.html –
Или, если вы этого не сделаете хотите, чтобы зависания Гуавы, просто определите свой собственный 'Поставщик' интерфейс в 'DefaultDict'. –
Soulman
Я бы предпочел бы построить 'DefaultDict' с моим собственным значением:' public DefaultDict (значение V) {this.value = value; } ' –