63

HashMap所以我对Java 中的 s有两个问题:

  1. 初始化 a 的正确方法是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[]中,第三个是字符串。这可以在 Java 中用HashMaps 做吗?另外,可以将 aHashMap作为值存储在 a 中HashMap吗?

4

9 回答 9

104

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

 Map x = new HashMap();

请注意,x输入为Map. 这使得将来更改实现(更改为 aTreeMap或 a )变得更加容易。LinkedHashMap

您可以使用泛型来确保一定程度的类型安全:

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

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

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

以上,虽然更冗长,但避免了编译器警告。在这种情况下,内容HashMap可以是 any Object,因此可以是Integer,int[]等,这就是您正在做的事情。

如果您仍在使用 Java 6,Guava Libraries(尽管您自己做起来很容易)有一个方法调用newHashMap(),它可以避免在您执行new. 它从变量声明中推断类型(这是 Java 7 之前的构造函数中不可用的 Java 特性)。

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

 x.put("one", Integer.valueOf(1));

您当然可以将 aHashMap作为值放在 another 中HashMap,但我认为如果您以递归方式执行此操作(即将 theHashMap作为值本身),则会出现问题。

于 2009-08-28T16:12:56.960 回答
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)。

于 2009-08-28T16:09:16.123 回答
4

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

如果您想做后者,请尝试将 map 声明为HashMap<String,Object>.

于 2009-08-28T16:05:30.733 回答
3

你写它的方式相当于

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

括号内的内容是您与编译器交流您将在 HashMap 中放入的内容,以便它可以为您进行错误检查。如果 Object, Object 是您真正想要的(可能不是),您应该明确声明它。通常,您应该尽可能明确地声明,以方便编译器进行错误检查。您所描述的内容可能应该这样声明:

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

这样,您至少可以声明您的键将是字符串,但您的值可以是任何东西。请记住,当您返回值时使用强制转换。

于 2009-08-28T16:21:42.417 回答
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 中的一个值。

于 2009-08-28T16:27:04.637 回答
1

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

在 Java 5 下,当您将 int(或任何原始类型)添加到集合时,它将自动装箱为 Integer(或其他相应类型)。不过要小心这一点,因为使用自动装箱有一些问题。

于 2009-08-28T16:08:44.377 回答
1

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

Map m = new HashMap();

这不能确保类型安全,但遵循将确保类型安全

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

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

于 2016-09-09T04:30:03.030 回答
1

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 ) ;
于 2019-09-18T23:31:22.877 回答
0

回答您的第二个问题:是的 HashMap 可以保存不同类型的对象。这是否是一个好主意取决于您要解决的问题。

也就是说,你的例子不起作用。int 值不是对象。您必须使用 Integer 包装类将 int 值存储在 HashMap 中

于 2009-08-28T16:14:53.070 回答