java.util转换。属性HashMap

时间:2021-08-09 19:38:17
Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?

java.util.Properties is a implement of Map, And HashMap constructor receive a Map type param. But why must convert explicitly?

java.util。属性是Map的实现,HashMap构造函数接收映射类型param。但是为什么要显式转换?

11 个解决方案

#1


68  

This is because Properties extends Hashtable<Object, Object> (which, in turn, implements Map<Object, Object>). You attempt to feed that into a Map<String, String>. It is therefore incompatible.

这是因为属性扩展了Hashtable (它依次实现Map )。您试图将其输入到Map 。因此不相容的。 ,> ,> ,>

You need to feed string properties one by one into your map...

您需要将字符串属性逐一输入到您的映射中……

For instance:

例如:

for (final String name: properties.stringPropertyNames())
    map.put(name, properties.getProperty(name));

#2


31  

The efficient way to do that is just to cast to a generic Map as follows:

这样做的有效方法是将其转换为一个泛型映射,如下所示:

Properties props = new Properties();

Map<String, String> map = (Map)props;

This will convert a Map<Object, Object> to a raw Map, which is "ok" for the compiler (only warning). Once we have a raw Map it will cast to Map<String, String> which it also will be "ok" (another warning). You can ignore them with annotation @SuppressWarnings({ "unchecked", "rawtypes" })

这将把Map 转换为原始映射,这对编译器来说是“ok”的(只有警告)。一旦我们有了一个原始的地图,它将转换成Map ,它也将是“ok”(另一个警告)。您可以使用注释@抑制警告({“未检查”,“rawtypes”})来忽略它们。 ,> ,>

This will work because in the JVM the object doesn't really have a generic type. Generic types are just a trick that verifies things at compile time.

这将起作用,因为在JVM中对象并没有真正的泛型类型。泛型类型只是在编译时验证事物的一个技巧。

If some key or value is not a String it will produce a ClassCastException error. With current Properties implementation this is very unlikely to happen, as long as you don't use the mutable call methods from the super Hashtable<Object,Object> of Properties.

如果某个键或值不是字符串,它将产生ClassCastException错误。对于当前的属性实现,这是不可能发生的,只要您不使用超级Hashtable 属性的可变调用方法。 ,object>

So, if don't do nasty things with your Properties instance this is the way to go.

所以,如果你的属性实例不做龌龊的事情,这就是方法。

#3


25  

How about this?

这个怎么样?

   Map properties = new Properties();
   Map<String, String> map = new HashMap<String, String>(properties);

Will cause a warning, but works without iterations.

会引起警告,但不会迭代。

#4


20  

You could use Google Guava's:

你可以用谷歌番石榴

com.google.common.collect.Maps.fromProperties(Properties)

com.google.common.collect.Maps.fromProperties(属性)

#5


14  

Properties implements Map<Object, Object> - not Map<String, String>.

属性实现Map - not Map ,> ,>

You're trying to call this constructor:

你要调用这个构造函数

public HashMap(Map<? extends K,? extends V> m)

... with K and V both as String.

…K和V都是字符串。

But Map<Object, Object> isn't a Map<? extends String, ? extends String>... it can contain non-string keys and values.

但是Map 不是Map …它可以包含非字符串键和值。 ,>

This would work:

这将工作:

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

... but it wouldn't be as useful to you.

…但它对你没用。

Fundamentally, Properties should never have been made a subclass of HashTable... that's the problem. Since v1, it's always been able to store non-String keys and values, despite that being against the intention. If composition had been used instead, the API could have only worked with string keys/values, and all would have been well.

从根本上说,属性不应该被创建为HashTable的子类……这就是问题所在。自v1以来,它总是能够存储非字符串键和值,尽管这违背了意图。如果使用组合,那么API只能使用字符串键/值,而且所有的都很好。

You may want something like this:

你可能想要这样的东西:

Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
    map.put(key, properties.getProperty(key));
}

#6


13  

The Java 8 way:

Java 8道:

properties.entrySet().stream().collect(
    Collectors.toMap(
         e -> e.getKey().toString(),
         e -> e.getValue().toString()
    )
);

#7


4  

If you know that your Properties object only contains <String, String> entries, you can resort to a raw type:

如果您知道您的属性对象仅包含 条目,您可以使用原始类型: ,>

Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);

#8


4  

The problem is that Properties implements Map<Object, Object>, whereas the HashMap constructor expects a Map<? extends String, ? extends String>.

问题是属性实现了Map ,而HashMap构造函数期望映射 。 ,>

This answer explains this (quite counter-intuitive) decision. In short: before Java 5, Properties implemented Map (as there were no generics back then). This meant that you could put any Object in a Properties object. This is still in the documenation:

这个答案解释了这个(相当反直觉的)决定。简而言之:在Java 5之前,属性实现了Map(那时还没有泛型)。这意味着您可以将任何对象放入属性对象中。这仍在文件中:

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead.

由于属性从Hashtable继承,put和putAll方法可以应用到Properties对象。由于它们允许调用者插入其键或值不是字符串的条目,因此它们的使用非常不理想。应该使用setProperty方法。

To maintain compatibility with this, the designers had no other choice but to make it inherit Map<Object, Object> in Java 5. It's an unfortunate result of the strive for full backwards compatibility which makes new code unnecessarily convoluted.

为了保持与此的兼容性,设计人员没有其他选择,只能让它继承Map 在Java 5中。这是为完全向后兼容而努力的不幸结果,这使得新代码不必要地令人费解。 ,>

If you only ever use string properties in your Properties object, you should be able to get away with an unchecked cast in your constructor:

如果您只在属性对象中使用字符串属性,那么您应该能够在构造函数中不受约束地进行转换:

Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);

or without any copies:

或没有任何副本:

Map<String, String> map = (Map<String, String>) properties;

#9


4  

I would use following Guava API: com.google.common.collect.Maps#fromProperties

我将使用以下的番石榴API: com.google.common.collect.Maps#fromProperties。

Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);

#10


1  

this is only because the constructor of HashMap requires an arg of Map generic type and Properties implements Map.

这仅仅是因为HashMap的构造函数需要一个Map泛型类型和属性实现映射的arg。

This will work, though with a warning

这将起作用,尽管有警告。

    Properties properties = new Properties();
    Map<String, String> map = new HashMap(properties);

#11


0  

First thing,

第一件事,

Properties class is based on Hashtable and not Hashmap. Properties class basically extends Hashtable

属性类基于Hashtable而不是Hashmap。属性类基本上扩展了Hashtable。

There is no such constructor in HashMap class which takes a properties object and return you a hashmap object. So what you are doing is NOT correct. You should be able to cast the object of properties to hashtable reference.

HashMap类中没有这样的构造函数,它获取一个属性对象并返回一个HashMap对象。所以你所做的是不正确的。您应该能够将属性的对象转换为hashtable引用。

#1


68  

This is because Properties extends Hashtable<Object, Object> (which, in turn, implements Map<Object, Object>). You attempt to feed that into a Map<String, String>. It is therefore incompatible.

这是因为属性扩展了Hashtable (它依次实现Map )。您试图将其输入到Map 。因此不相容的。 ,> ,> ,>

You need to feed string properties one by one into your map...

您需要将字符串属性逐一输入到您的映射中……

For instance:

例如:

for (final String name: properties.stringPropertyNames())
    map.put(name, properties.getProperty(name));

#2


31  

The efficient way to do that is just to cast to a generic Map as follows:

这样做的有效方法是将其转换为一个泛型映射,如下所示:

Properties props = new Properties();

Map<String, String> map = (Map)props;

This will convert a Map<Object, Object> to a raw Map, which is "ok" for the compiler (only warning). Once we have a raw Map it will cast to Map<String, String> which it also will be "ok" (another warning). You can ignore them with annotation @SuppressWarnings({ "unchecked", "rawtypes" })

这将把Map 转换为原始映射,这对编译器来说是“ok”的(只有警告)。一旦我们有了一个原始的地图,它将转换成Map ,它也将是“ok”(另一个警告)。您可以使用注释@抑制警告({“未检查”,“rawtypes”})来忽略它们。 ,> ,>

This will work because in the JVM the object doesn't really have a generic type. Generic types are just a trick that verifies things at compile time.

这将起作用,因为在JVM中对象并没有真正的泛型类型。泛型类型只是在编译时验证事物的一个技巧。

If some key or value is not a String it will produce a ClassCastException error. With current Properties implementation this is very unlikely to happen, as long as you don't use the mutable call methods from the super Hashtable<Object,Object> of Properties.

如果某个键或值不是字符串,它将产生ClassCastException错误。对于当前的属性实现,这是不可能发生的,只要您不使用超级Hashtable 属性的可变调用方法。 ,object>

So, if don't do nasty things with your Properties instance this is the way to go.

所以,如果你的属性实例不做龌龊的事情,这就是方法。

#3


25  

How about this?

这个怎么样?

   Map properties = new Properties();
   Map<String, String> map = new HashMap<String, String>(properties);

Will cause a warning, but works without iterations.

会引起警告,但不会迭代。

#4


20  

You could use Google Guava's:

你可以用谷歌番石榴

com.google.common.collect.Maps.fromProperties(Properties)

com.google.common.collect.Maps.fromProperties(属性)

#5


14  

Properties implements Map<Object, Object> - not Map<String, String>.

属性实现Map - not Map ,> ,>

You're trying to call this constructor:

你要调用这个构造函数

public HashMap(Map<? extends K,? extends V> m)

... with K and V both as String.

…K和V都是字符串。

But Map<Object, Object> isn't a Map<? extends String, ? extends String>... it can contain non-string keys and values.

但是Map 不是Map …它可以包含非字符串键和值。 ,>

This would work:

这将工作:

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

... but it wouldn't be as useful to you.

…但它对你没用。

Fundamentally, Properties should never have been made a subclass of HashTable... that's the problem. Since v1, it's always been able to store non-String keys and values, despite that being against the intention. If composition had been used instead, the API could have only worked with string keys/values, and all would have been well.

从根本上说,属性不应该被创建为HashTable的子类……这就是问题所在。自v1以来,它总是能够存储非字符串键和值,尽管这违背了意图。如果使用组合,那么API只能使用字符串键/值,而且所有的都很好。

You may want something like this:

你可能想要这样的东西:

Map<String, String> map = new HashMap<String, String>();
for (String key : properties.stringPropertyNames()) {
    map.put(key, properties.getProperty(key));
}

#6


13  

The Java 8 way:

Java 8道:

properties.entrySet().stream().collect(
    Collectors.toMap(
         e -> e.getKey().toString(),
         e -> e.getValue().toString()
    )
);

#7


4  

If you know that your Properties object only contains <String, String> entries, you can resort to a raw type:

如果您知道您的属性对象仅包含 条目,您可以使用原始类型: ,>

Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>((Map) properties);

#8


4  

The problem is that Properties implements Map<Object, Object>, whereas the HashMap constructor expects a Map<? extends String, ? extends String>.

问题是属性实现了Map ,而HashMap构造函数期望映射 。 ,>

This answer explains this (quite counter-intuitive) decision. In short: before Java 5, Properties implemented Map (as there were no generics back then). This meant that you could put any Object in a Properties object. This is still in the documenation:

这个答案解释了这个(相当反直觉的)决定。简而言之:在Java 5之前,属性实现了Map(那时还没有泛型)。这意味着您可以将任何对象放入属性对象中。这仍在文件中:

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead.

由于属性从Hashtable继承,put和putAll方法可以应用到Properties对象。由于它们允许调用者插入其键或值不是字符串的条目,因此它们的使用非常不理想。应该使用setProperty方法。

To maintain compatibility with this, the designers had no other choice but to make it inherit Map<Object, Object> in Java 5. It's an unfortunate result of the strive for full backwards compatibility which makes new code unnecessarily convoluted.

为了保持与此的兼容性,设计人员没有其他选择,只能让它继承Map 在Java 5中。这是为完全向后兼容而努力的不幸结果,这使得新代码不必要地令人费解。 ,>

If you only ever use string properties in your Properties object, you should be able to get away with an unchecked cast in your constructor:

如果您只在属性对象中使用字符串属性,那么您应该能够在构造函数中不受约束地进行转换:

Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);

or without any copies:

或没有任何副本:

Map<String, String> map = (Map<String, String>) properties;

#9


4  

I would use following Guava API: com.google.common.collect.Maps#fromProperties

我将使用以下的番石榴API: com.google.common.collect.Maps#fromProperties。

Properties properties = new Properties();
Map<String, String> map = Maps.fromProperties(properties);

#10


1  

this is only because the constructor of HashMap requires an arg of Map generic type and Properties implements Map.

这仅仅是因为HashMap的构造函数需要一个Map泛型类型和属性实现映射的arg。

This will work, though with a warning

这将起作用,尽管有警告。

    Properties properties = new Properties();
    Map<String, String> map = new HashMap(properties);

#11


0  

First thing,

第一件事,

Properties class is based on Hashtable and not Hashmap. Properties class basically extends Hashtable

属性类基于Hashtable而不是Hashmap。属性类基本上扩展了Hashtable。

There is no such constructor in HashMap class which takes a properties object and return you a hashmap object. So what you are doing is NOT correct. You should be able to cast the object of properties to hashtable reference.

HashMap类中没有这样的构造函数,它获取一个属性对象并返回一个HashMap对象。所以你所做的是不正确的。您应该能够将属性的对象转换为hashtable引用。