首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有没有对应于Python的defaultdict的Java版本?

有没有对应于Python的defaultdict的Java版本?
EN

Stack Overflow用户
提问于 2009-11-24 05:42:19
回答 8查看 13.4K关注 0票数 50

在Python语言中,defaultdict类提供了一种从key -> [list of values]创建映射的便捷方法,如下例所示:

代码语言:javascript
运行
复制
from collections import defaultdict
d = defaultdict(list)
d[1].append(2)
d[1].append(3)
# d is now {1: [2, 3]}

在Java中有没有这样的等价物?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-11-28 19:08:11

没有任何东西提供默认字典的开箱即用行为。然而,在Java中创建您自己的默认字典并不那么困难。

代码语言:javascript
运行
复制
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;
    }    
}

这个类的用法如下:

代码语言:javascript
运行
复制
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);
}

下面的代码将打印:{1=[2, 3]}

票数 32
EN

Stack Overflow用户

发布于 2015-06-22 04:04:28

在最常见的情况下,你想要一个defaultdict,你会更喜欢一个设计得当的多地图或多集,这才是你真正想要的。Multimap是一个键->集合映射(缺省为空集合),Multiset是一个键->整数映射(缺省值为零)。

Guava提供了这两种Multimaps and Multisets的非常好的实现,几乎涵盖了所有用例。

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

顾名思义,

  • getOrDefault(),返回值,或者返回默认值。这不会将默认值存储在map.
  • computeIfAbsent()中,而是从提供的函数中计算值(该函数可能始终返回相同的默认值),并在返回之前将计算出的值存储在地图中。

如果你想封装这些调用,你可以使用Guava的ForwardingMap

代码语言:javascript
运行
复制
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());
  }
}

然后像这样构造你的默认地图:

代码语言:javascript
运行
复制
Map<String, List<String>> defaultMap = DefaultMap.create(ArrayList::new);
票数 14
EN

Stack Overflow用户

发布于 2009-11-24 06:00:23

除了apache集合之外,还要检查google collections

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

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1786206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档