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() 写下来()?