是否存在Python的Java等价物';什么是迪克特?

是否存在Python的Java等价物';什么是迪克特?,java,python,hashmap,Java,Python,Hashmap,在Python中,defaultdict类提供了从key->[list of values]创建映射的便捷方法,在下面的示例中 从集合导入defaultdict d=默认DICT(列表) d[1]。追加(2) d[1]。追加(3) #d现在是{1:[2,3]} Java中是否有与此等效的版本?您可以从中使用。除了apache集合之外,还可以检查: 类似于映射的集合,但可以将多个值与单个键关联。如果使用相同的键但不同的值调用put(K,V)两次,则多重映射包含从键到两个值的映射 仅使用Java运

在Python中,
defaultdict
类提供了从
key->[list of values]
创建映射的便捷方法,在下面的示例中

从集合导入defaultdict
d=默认DICT(列表)
d[1]。追加(2)
d[1]。追加(3)
#d现在是{1:[2,3]}

Java中是否有与此等效的版本?

您可以从中使用。

除了apache集合之外,还可以检查:

类似于映射的集合,但可以将多个值与单个键关联。如果使用相同的键但不同的值调用put(K,V)两次,则多重映射包含从键到两个值的映射


仅使用Java运行时库,您就可以使用
HashMap
并添加
ArrayList
,在键不存在时保存您的值,或者在键存在时将值添加到列表中。

没有现成的默认dict行为。然而,用Java创建自己的默认dict并不是那么困难

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class DefaultDict<K, V> extends HashMap<K, V> {

    Class<V> klass;
    public DefaultDict(Class klass) {
        this.klass = klass;    
    }

    @Override
    public V get(Object key) {
        V returnValue = super.get(key);
        if (returnValue == null) {
            try {
                returnValue = klass.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            this.put((K) key, returnValue);
        }
        return returnValue;
    }    
}
import java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
公共类DefaultDict扩展HashMap{
克拉斯类;
公共默认DICT(klass类){
this.klass=klass;
}
@凌驾
public V get(对象键){
V returnValue=super.get(键);
if(returnValue==null){
试一试{
returnValue=klass.newInstance();
}捕获(例外e){
抛出新的运行时异常(e);
}
此.put((K)键,返回值);
}
返回值;
}    
}
此类可按如下方式使用:

public static void main(String[] args) {
    DefaultDict<Integer, List<Integer>> dict =
        new DefaultDict<Integer, List<Integer>>(ArrayList.class);
    dict.get(1).add(2);
    dict.get(1).add(3);
    System.out.println(dict);
}
publicstaticvoidmain(字符串[]args){
默认命令=
新的DefaultDict(ArrayList.class);
dict.get(1).添加(2);
dict.get(1).添加(3);
系统输出打印项次(dict);
}

此代码将打印:
{1=[2,3]}

来自@tendayi mawushe的解决方案不适用于基本类型(例如
实例化异常整数
),下面是一个适用于整数、双精度、浮点的实现。为了方便起见,我经常使用这些映射并添加静态构造函数

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 java.util.HashMap;
导入java.util.Map;
/**模拟Python的defaultdict的行为*/
公共类DefaultHashMap扩展了HashMap{
私有静态最终长serialVersionUID=1L;
私人期末班;
私有最终值;
@SuppressWarnings({“rawtypes”,“unchecked”})
公共DefaultHashMap(类工厂){
this.cls=工厂;
this.defaultValue=null;
}
公共DefaultHashMap(数字defaultValue){
this.cls=null;
this.defaultValue=defaultValue;
}
@抑制警告(“未选中”)
@凌驾
public V get(对象键){
V值=super.get(键);
如果(值==null){
if(defaultValue==null){
试一试{
value=cls.newInstance();
}捕获(例外e){
e、 printStackTrace();
}
}否则{
值=(V)默认值;
}
这个.put((K)键,值);
}
返回值;
}
公共静态映射intDefaultMap(){
返回新的DefaultHashMap(0);
}
公共静态映射doubleDefaultMap(){
返回新的DefaultHashMap(0d);
}
公共静态映射floatDefaultMap(){
返回新的DefaultHashMap(0f);
}
公共静态映射stringDefaultMap(){
返回新的DefaultHashMap(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"));
    }
}
导入静态org.junit.Assert.assertEquals;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Map;
导入org.junit.Test;
公共类DefaultHashMapTest{
@试验
公开无效测试(){
Map dm=新的DefaultHashMap(
ArrayList.class);
dm.get(“nokey”)。添加(“一”);
dm.get(“nokey”)。添加(“两个”);
assertEquals(2,dm.get(“nokey”).size());
assertEquals(0,dm.get(“nokey2”).size());
}
@试验
公开无效证明(){
Map dm=DefaultHashMap.intDefaultMap();
assertEquals(新整数(0),dm.get(“nokey”);
assertEquals(新整数(0),dm.get(“nokey2”);
dm.put(“nokey”,3);
assertEquals(新整数(0),dm.get(“nokey2”);
dm.put(“nokey3”,3);
assertEquals(新整数(3),dm.get(“nokey3”);
}
@试验
公共void testString(){
Map dm=DefaultHashMap.stringDefaultMap();
assertEquals(“,dm.get”(“nokey”);
dm.put(“nokey1”、“mykey”);
assertEquals(“mykey”,dm.get(“nokey1”);
}
}

在最常见的情况下,如果您想要一个
defaultdict
,那么使用正确设计的Multimap或Multiset,您会更开心,这正是您真正想要的。多重映射是键->集合映射(默认为空集合),多重集是键->整数映射(默认为零)

这两种方法都提供了非常好的实现,将涵盖几乎所有的用例

但是(这就是为什么我发布了一个新的答案)使用Java8,您现在可以用任何现有的
Map
复制
defaultdict
的剩余用例

  • ,顾名思义,返回值(如果存在),或返回默认值。这不会在地图中存储默认值
  • 从提供的函数中计算值(该函数始终可以返回相同的默认值),并在返回之前将计算出的值存储在映射中
如果您想封装这些调用,可以使用番石榴:

public类DefaultMap扩展了ForwardingMap{
私人最终地图代表;
私人最终供应商违约供应商;
/**
*创建一个映射,该映射使用给定值作为所有对象的默认值
*钥匙,你应该戴上
public class DefaultMap<K, V> extends ForwardingMap<K, V> {
  private final Map<K, V> delegate;
  private final Supplier<V> defaultSupplier;

  /**
   * Creates a map which uses the given value as the default for <i>all</i>
   * keys. You should only use immutable values as a shared default key.
   * Prefer {@link #create(Supplier)} to construct a new instance for each key.
   */
  public static DefaultMap<K, V> create(V defaultValue) {
    return create(() -> defaultValue);
  }

  public static DefaultMap<K, V> create(Supplier<V> defaultSupplier) {
    return new DefaultMap<>(new HashMap<>(), defaultSupplier);
  }

  public DefaultMap<K, V>(Map<K, V> delegate, Supplier<V> defaultSupplier) {
    this.delegate = Objects.requireNonNull(delegate);
    this.defaultSupplier = Objects.requireNonNull(defaultSupplier);
  }

  @Override
  public V get(K key) {
    return delegate().computeIfAbsent(key, k -> defaultSupplier.get());
  }
}
Map<String, List<String>> defaultMap = DefaultMap.create(ArrayList::new);
DefaultHashMap<Integer, List<String>> map = new DefaultHashMap(() -> new ArrayList<>());
map.get(11).add("first");
map.computeIfAbsent(1, k -> new ArrayList<Integer>()).add(2);