Java HashMap - 是不是有必要为每个集合使用 .put()? [复制]

Posted

技术标签:

【中文标题】Java HashMap - 是不是有必要为每个集合使用 .put()? [复制]【英文标题】:Java HashMap - Is it necessary to use .put() for each set? [duplicate]Java HashMap - 是否有必要为每个集合使用 .put()? [复制] 【发布时间】:2015-07-16 17:22:24 【问题描述】:

想象以下场景。您有一组已经可以访问和知道的值。出于某种原因,您必须将它们放入 HashMap 中。

代码示例:

String a = "a";
Strinb b = "b";
...
HashMap map = new HashMap(5);
map.put("a", a);
map.put("b", b);
...

真的有必要这样做吗?我不敢相信没有一个构造函数可以让你从头开始输入你的值。

我说的是这样的:

HashMap map = new HashMap(<"a", a>, <"b", b>, ...);

甚至是这样的:

HashMap map = new HashMap(5);
HashMap.putBunchOfStuff("a", a, "b", b, ...);

编辑:我的意图是问是否有方法,但更重要的是如果答案是“否”,为什么没有这样的构造函数/方法。强>

【问题讨论】:

Idk 如果 Java8 有一些新的诡计与否。但是几年前有人问过this 的问题,共识是否定的。另见this 你不能这样做......但是你可以通过使用 putAll(Map(K,v)); 来添加另一个地图。 不知道是不是一开始就可以访问,为什么不用enums,或者如果你不喜欢key和value的重复,那为什么不Set ,或者您可以在定义 put(Object o) 的位置创建“MyHashMap” @CsBalazsHungary 实际问题稍微复杂一点。这只是伪代码。 @OddDev 您应该始终提供尽可能接近实际代码的代码。否则你可能会解决错误的问题。 【参考方案1】:

不幸的是,集合文字在 Java 7(和 Java 8)中是 proposal for Project Coin,但 它从未进入最终产品,也就是说它不是Java的特性。

命题是这样的

Here’s how it would look with map literals:


    final Map<Integer, String> platonicSolids =  
          4 : "tetrahedron",
          6 : "cube", 
          8 : "octahedron", 
          12 : "dodecahedron", 
          20 : "icosahedron"
    ;


Here is the empty map literal, which has a slightly irregular syntax to make
it differ from the empty set:


    Map<String, Integer> noJokeHere =  : ;

但它从未发生过,所以很遗憾,这不起作用。因此,除非您编写自己的魔法构建器或像on this site of Per-Åke Minborg 这样的花哨的 lambda,否则您只能靠自己。不过,该站点的以下内容应该可以工作(在 Java 8 中)。

//copy paste from linked site
Map<Integer, String> map = Stream.of(
            new SimpleEntry<>(0, "zero"),
            new SimpleEntry<>(1, "one"),
            //...
            new SimpleEntry<>(11, "eleven"),
            new SimpleEntry<>(12, "twelve"))
            .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()));

还有简化版,同样来自site:

//copy paste from linked site
public static <K, V> Map.Entry<K, V> entry(K key, V value) 
    return new AbstractMap.SimpleEntry<>(key, value);


public static <K, U> Collector<Map.Entry<K, U>, ?, Map<K, U>> entriesToMap() 
    return Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue());


Map<Integer, String> map = Stream.of(
            entry(0, "zero"),
            //...
            entry(12, "twelve"))
            .collect(entriesToMap());

由于these points,没有引入集合字面量:

此功能的“简单”版本(仅限集合、列表、地图)不是 非常令人满意或受欢迎;此功能的“可扩展”版本是 开放式、凌乱的,并且几乎可以保证会超出其设计 预算;

基于库的版本为我们提供了 1% 的 X% 的收益 成本,其中 X >> 1;

值类型即将到来,以及“此功能会是什么样子” 在具有值类型的世界中可能与在世界中完全不同 没有,暗示尝试做这项工作是有问题的 在值类型之前;

我们最好将我们的语言设计带宽集中在 解决更多基于图书馆的基础问题 版本(包括:更高效的可变参数、数组常量 常量池、不可变数组以及对缓存(和回收)的支持 在压力下)中间不可变的结果)。

By Brian Goetz from Oracle

【讨论】:

...你的意思是第二个,对吧?第一个是提议。那从未发生过。 不,我说的是一般的答案。非常好,清晰的信息,正是我正在寻找的信息。获取代码 sn-p 不是我的意图。 啊,在这种情况下,我很高兴你发现它有帮助,不客气! :)【参考方案2】:

默认情况下没有这样的构造函数 - 您可以在实例化时使用双括号习惯用法 put 映射中的所有值,但这仍然需要多次 put 调用:

Map<String,String> map = new HashMap<>() 
    put("a", "val1");
    put("b", "val2");
    //etc.
;

实际上,您通常希望将大块数据放入可从流或其他集合访问的地图中,因此在这种情况下循环多个 put 调用很简单。

Guava 在其ImmutableMap.Builder 上有一个putAll(),使您能够在实例化之前执行类似的操作。其他外部库可能有其他类似的行为,但事实是您必须求助于使用外部库。

【讨论】:

注意:双括号初始化会创建一个匿名子类,如果在非静态上下文中使用,它会保持对外部实例的强引用(从而使其保持活动状态)。 @Radiodef 这是真的——我根本不觉得它是一个理想的习语(这更像是一种晦涩的语法意外,而不是专门为此用途而设计的。)【参考方案3】:

可以创建一个漂亮的实用方法来使用可变参数创建地图。

例子:

@SuppressWarnings("unchecked")
public static <K, V> HashMap<K, V> newMap(Object... elems) 
    HashMap<K, V> m = new HashMap<K, V>();

    for (int i = 0; i < elems.length; i += 2) 
        m.put((K) elems[i], (V) elems[i + 1]);    
    

    return m;


Map<String, Integer> m = newMap("k1", 1, "k2", 2);        

注意:这不是类型安全的,如果您在使用时出错,可能会导致映射包含错误类型的对象,将ClassCastException 扔到意想不到的地方。这称为heap pollution。示例:

Map<String, Integer> m = newMap("k1", 1, "k2", "2");
int s = m.get("k2");  // ClassCastException!

【讨论】:

【参考方案4】:

你可以使用类似的东西:

HashMap<String, String> map = new HashMap<String, String>(5)
    put("a", "a");
    put("b", "b");
;

但我不知道你是否可以使用局部变量 a 和 b。

【讨论】:

注意:这会创建一个匿名子类,如果在非静态上下文中使用,它会保持对外部实例的强引用(从而使其保持活动状态)。

以上是关于Java HashMap - 是不是有必要为每个集合使用 .put()? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 laravel 的迁移中是不是有必要为每个 up() 写下来()?

Java中的HashMap

如何在一个类中实现异步

什么时候在java中使用linkedhashmap而不是hashmap?

Java入门系列之集合HashMap源码分析(十四)

Java hashmap 搜索真的是 O(1) 吗?