所以我在Java中有两个关于HashMap
的问题:
初始化HashMap
的正确方法是什么?我认为在我的情况下使用可能是最好的:
HashMap x = new HashMap();
但Eclipse一直建议我使用:
HashMap<something, something> map = new HashMap();
哪个更好?
HashMap
可以将不同类型的对象/数据类型作为值保存吗?例如,这样做是否正常:
map.put("one", 1);
map.put("two", {1, 2});
map.put("three", "hello");
在第一个put()
中,我希望int
为值,第二个为int[]
,第三个为字符串。使用HashMap
s在Java中可以做到这一点吗?此外,是否可以将HashMap
作为值存储在HashMap
中?
答案 0 :(得分:100)
这实际上取决于您需要何种类型的安全性。这种非通用的方式最好是:
Map x = new HashMap();
请注意,x
的输入为Map
。这样可以更加轻松地在将来更改实施(TreeMap
或LinkedHashMap
)。
您可以使用泛型来确保某种级别的类型安全:
Map<String, Object> x = new HashMap<String, Object>();
在Java 7及更高版本中,您可以执行
Map<String, Object> x = new HashMap<>();
以上,虽然更详细,但避免了编译器警告。在这种情况下,HashMap
的内容可以是任意Object
,因此您可以Integer
,int[]
等等。
如果您仍在使用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
可以是任何类型,例如String
,Integer
等。
答案 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 ) ;