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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1347949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:29:10  来源:igfitidea点击:

Correct way to initialize HashMap and can HashMap hold different value types?

javastandardshashmap

提问by Tony Stark

So I have two questions about HashMaps in Java:

所以我有两个关于HashMapJava 中的 s 的问题:

  1. What is the correct way to initialize a HashMap? I think it might be best in my situation to use:

    HashMap x = new HashMap();
    

    But Eclipse keeps suggesting that I use:

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

    Which is better?

  2. Can a HashMaphold different types of objects/data types as values? For example, would this work and be OK:

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

    In the first put(), I want an intas a value, in the second an int[], and third a string. Is this okay to do in Java with HashMaps? Also, is it okay to store a HashMapas a value within a HashMap?

  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吗?

采纳答案by Yishai

It really depends on what kind of type safety you need. The non-generic way of doing it is best done as:

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

 Map x = new HashMap();

Note that xis typed as a Map. this makes it much easier to change implementations (to a TreeMapor a LinkedHashMap) in the future.

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

You can use generics to ensure a certain level of type safety:

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

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

In Java 7 and later you can do

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

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

The above, while more verbose, avoids compiler warnings. In this case the content of the HashMapcan be any Object, so that can be Integer, int[], etc. which is what you are doing.

以上虽然更冗长,但避免了编译器警告。在这种情况下的内容HashMap可以是任意Object,这样可以Integerint[]等这是你在做什么。

If you are still using Java 6, Guava Libraries(although it is easy enough to do yourself) has a method called newHashMap()which avoids the need to duplicate the generic typing information when you do a new. It infers the type from the variable declaration (this is a Java feature not available on constructors prior to Java 7).

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

By the way, when you add an int or other primitive, Java is autoboxing it. That means that the code is equivalent to:

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

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

You can certainly put a HashMapas a value in another HashMap, but I think there are issues if you do it recursively (that is put the HashMapas a value in itself).

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

回答by Paul Tomblin

Eclipse is recommending that you declare the type of the HashMap because that enforces some type safety. Of course, it sounds like you're trying to avoid type safety from your second part.

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

If you want to do the latter, try declaring map as HashMap<String,Object>.

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

回答by Ken Liu

A HashMap can hold any object as a value, even if it is another HashMap. Eclipse is suggesting that you declare the types because that is the recommended practice for Collections. under Java 5. You are free to ignore Eclipse's suggestions.

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

Under Java 5, an int (or any primitive type) will be autoboxedinto an Integer (or other corresponding type) when you add it to a collection. Be careful with this though, as there are some catches to using autoboxing.

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

回答by MBCook

This is a change made with Java 1.5. What you list first is the old way, the second is the new way.

这是 Java 1.5 所做的更改。您列出的第一个是旧方式,第二个是新方式。

By using HashMap you can do things like:

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

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

....

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

If you didn't have the types on the map, you'd have to do this:

如果地图上没有这些类型,则必须执行以下操作:

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

It's really very useful. It helps you catch bugs and avoid writing all sorts of extra casts. It was one of my favorite features of 1.5 (and newer).

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

You can still put multiple things in the map, just specify it as Map, then you can put any object in (a String, another Map, and Integer, and three MyObjects if you are so inclined).

您仍然可以在地图中放置多个东西,只需将其指定为地图,然后您就可以放入任何对象(一个字符串、另一个地图和整数,如果您愿意,还可以放入三个 MyObject)。

回答by Luke

In answer to your second question: Yes a HashMap can hold different types of objects. Whether that's a good idea or not depends on the problem you're trying to solve.

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

That said, your example won't work. The int value is not an Object. You have to use the Integer wrapper class to store an int value in a HashMap

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

回答by Graphics Noob

The way you're writing it is equivalent to

你写它的方式相当于

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

What goes inside the brackets is you communicating to the compiler what you're going to put in the HashMap so that it can do error checking for you. If Object, Object is what you actually want (probably not) you should explicitly declare it. In general you should be as explicit as you can with the declaration to facilitate error checking by the compiler. What you've described should probably be declared like this:

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

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

That way you at least declare that your keys are going to be strings, but your values can be anything. Just remember to use a cast when you get a value back out.

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

回答by Billy Bob Bain

The 2nd one is using generics which came in with Java 1.5. It will reduce the number of casts in your code & can help you catch errors at compiletime instead of runtime. That said, it depends on what you are coding. A quick & dirty map to hold a few objects of various types doesn't need generics. But if the map is holding objects all descending from a type other than Object, it can be worth it.

第二个是使用 Java 1.5 中的泛型。它将减少代码中的强制转换次数,并且可以帮助您在编译时而不是运行时捕获错误。也就是说,这取决于您正在编码的内容。一个快速而肮脏的地图来保存各种类型的几个对象不需要泛型。但是,如果地图保存的所有对象都来自 Object 以外的类型,那么它可能是值得的。

The prior poster is incorrect about the array in a map. An array is actually an object, so it is a valid value.

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

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

Also, since HashMap is an object, it can also be a value in a HashMap.

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

回答by Billy Bob Bain

Eclipse is suggesting you to define generic typeso that you can have type safety. You can write

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

Map m = new HashMap();

which does not ensure type safety but following will ensure type safety

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

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

The Objectcan be any type such as String, Integeretc.

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

回答by Basil Bourque

Map.ofliterals

Map.of文字

As of Java 9, there is yet another way to instantiate a Map. You can create an unmodifiable map from zero, one, or several pairs of objects in a single-line of code. This is quite convenient in many situations.

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

For an empty Mapthat cannot be modified, call Map.of(). Why would you want an empty set that cannot be changed? One common case is to avoid returning a NULL where you have no valid content.

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

For a single key-value pair, call Map.of( myKey , myValue ). For example, Map.of( "favorite_color" , "purple" ).

对于单个键值对,调用Map.of( myKey , myValue ). 例如,Map.of( "favorite_color" , "purple" )

For multiple key-value pairs, use a series of key-value pairs. ``Map.of( "favorite_foreground_color" , "purple" , "favorite_background_color" , "cream" )`.

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

If those pairs are difficult to read, you may want to use Map.ofand pass Map.Entryobjects.

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

Note that we get back an object of the Mapinterface. We do not know the underlying concrete class used to make our object. Indeed, the Java team is free to used different concrete classes for different data, or to vary the class in future releases of Java.

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

The rules discussed in other Answers still apply here, with regard to type-safety. You declare your intended types, and your passed objects must comply. If you want values of various types, use Object.

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

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