正确的方法来初始化HashMap并且HashMap可以保存不同的值类型吗?

时间:2009-08-28 16:01:57

标签: java standards hashmap

所以我在Java中有两个关于HashMap的问题:

  1. 初始化HashMap的正确方法是什么?我认为在我的情况下使用可能是最好的:

    HashMap x = new HashMap();
    

    但Eclipse一直建议我使用:

    HashMap<something, something> map = new HashMap();
    

    哪个更好?

  2. HashMap可以将不同类型的对象/数据类型作为值保存吗?例如,这样做是否正常:

    map.put("one", 1);
    map.put("two", {1, 2});
    map.put("three", "hello");
    

    在第一个put()中,我希望int为值,第二个为int[],第三个为字符串。使用HashMap s在Java中可以做到这一点吗?此外,是否可以将HashMap作为值存储在HashMap中?

9 个答案:

答案 0 :(得分:100)

这实际上取决于您需要何种类型的安全性。这种非通用的方式最好是:

 Map x = new HashMap();

请注意,x的输入为Map。这样可以更加轻松地在将来更改实施(TreeMapLinkedHashMap)。

您可以使用泛型来确保某种级别的类型安全:

Map<String, Object> x = new HashMap<String, Object>();

在Java 7及更高版本中,您可以执行

Map<String, Object> x = new HashMap<>();

以上,虽然更详细,但避免了编译器警告。在这种情况下,HashMap的内容可以是任意Object,因此您可以Integerint[]等等。

如果您仍在使用Java 6,Guava Libraries(虽然很容易自己完成)有一个名为newHashMap()的方法,它可以避免在执行{{{}}时复制通用类型信息的需要{1}}。它从变量声明中推断出类型(这是Java 7之前的构造函数上不可用的Java特性)。

顺便说一句,当你添加一个int或其他原语时,Java会自动添加它。这意味着代码等同于:

new

你当然可以将 x.put("one", Integer.valueOf(1)); 作为一个值放在另一个HashMap中,但我认为如果你以递归的方式存在问题(将HashMap作为一个值放在其自身中)。

答案 1 :(得分:14)

这是使用Java 1.5进行的更改。你首先列出的是旧的方式,第二种是新的方式。

通过使用HashMap,您可以执行以下操作:

HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();

....

Doohickey result = ourMap.get("bob");

如果地图上没有类型,则必须执行此操作:

Doohickey result = (Doohickey) ourMap.get("bob");

这非常有用。它可以帮助您捕获错误并避免编写各种额外的强制转换。这是我最喜欢的1.5(和更新)功能之一。

您仍然可以在地图中放置多个内容,只需将其指定为Map,然后您可以将任何对象放入(String,另一个Map和Integer,以及三个MyObjects,如果您愿意的话)。

答案 2 :(得分:4)

Eclipse建议您声明HashMap的类型,因为这会强制执行某些类型的安全性。当然,听起来你正试图从第二部分开始避免类型安全。

如果您想要执行后者,请尝试将地图声明为HashMap<String,Object>

答案 3 :(得分:3)

你写它的方式相当于

HashMap<Object, Object> map = new HashMap<Object, Object>();

括号内的内容是您将与HashMap中的内容进行通信,以便它可以为您进行错误检查。如果Object,Object是您实际想要的(可能不是),您应该明确声明它。通常,您应该尽可能明确地使用声明来促进编译器进行错误检查。您所描述的内容应该像这样声明:

HashMap<String, Object> map = new HashMap<String, Object>();

这样你至少可以声明你的键是字符串,但你的值可以是任何东西。只要记得在退出值时使用演员表。

答案 4 :(得分:2)

第二个是使用Java 1.5引入的泛型。它会减少代码中的强制转换数量。可以帮助您在编译时而不是运行时捕获错误。也就是说,这取决于你编码的是什么。快速和快速脏地图可以容纳几种不同类型的对象,不需要泛型。但是如果地图持有的对象都是从Object以外的类型下降的,那么它就值得了。

关于地图中阵列的先前海报不正确。数组实际上是一个对象,因此它是一个有效的值。

Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object

此外,由于HashMap是一个对象,它也可以是HashMap中的值。

答案 5 :(得分:1)

HashMap可以将任何对象保存为值,即使它是另一个HashMap。 Eclipse建议您声明类型,因为这是集合的推荐做法。在Java 5下。您可以自由地忽略Eclipse的建议。

在Java 5中,当您将int(或任何基本类型)添加到集合中时,它将autoboxed成为整数(或其他相应类型)。但要小心,因为使用自动装箱有一些问题。

答案 6 :(得分:1)

Eclipse建议您定义generic type,以便拥有type safety。你可以写

Map m = new HashMap();

不保证类型安全,但以下将确保类型安全

Map<Object,Object> = new HashMap<Object,Object>();

Object可以是任何类型,例如StringInteger等。

答案 7 :(得分:0)

回答第二个问题:是的,HashMap可以容纳不同类型的对象。这是否是一个好主意取决于你试图解决的问题。

那就是说,你的例子是行不通的。 int值不是Object。您必须使用Integer包装类在HashMap中存储int值

答案 8 :(得分:0)

Map.of文字

从Java 9开始,还有另一种实例化Map的方法。您可以在一行代码中从零个,一对或几对对象创建一个不可修改的映射。在许多情况下这非常方便。

对于无法修改的空白Map,请致电Map.of()。为什么要一个不能更改的空集?一种常见情况是避免在没有有效内容的情况下返回NULL。

对于单个键值对,请致电Map.of( myKey , myValue )。例如,Map.of( "favorite_color" , "purple" )

对于多个键值对,请使用一系列键值对。 ``Map.of(“ favorite_foreground_color”,“ purple”,“ favorite_background_color”,“ cream”)`。

如果这些对难以阅读,则可能要使用Map.of并传递Map.Entry对象。

请注意,我们返回了Map接口的对象。我们不知道用于制作对象的基础具体类。实际上,Java团队可以自由地为不同的数据使用不同的具体类,或者在Java的未来版本中更改类。

在其他答案中讨论的规则在这里仍然适用于类型安全。您声明预期的类型,并且传递的对象必须符合。如果需要各种类型的值,请使用Object

Map< String , Color > preferences = Map.of( "favorite_color" , Color.BLUE ) ;