将java.util.Properties转换为HashMap <string,string> </string,string>

时间:2013-06-20 08:51:53

标签: java

Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?

java.util.Properties是Map的一个实现,而HashMap构造函数接收一个Map类型的param。 但为什么必须明确转换?

14 个答案:

答案 0 :(得分:79)

这是因为Properties extends Hashtable<Object, Object>(反过来,它实现了Map<Object, Object>)。您尝试将其反馈到Map<String, String>。因此它是不相容的。

您需要逐个将字符串属性提供给地图...

例如:

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

答案 1 :(得分:37)

这样做的有效方法就是按如下方式转换为通用Map:

Properties props = new Properties();

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

这会将Map<Object, Object>转换为原始地图,对编译器来说是“ok”(仅警告)。一旦我们有一个原始Map,它将转换为Map<String, String>,它也将是“ok”(另一个警告)。您可以使用注释@SuppressWarnings({ "unchecked", "rawtypes" })

忽略它们

这将起作用,因为在JVM中,对象实际上没有泛型类型。通用类型只是在编译时验证事物的技巧。

如果某个键或值不是String,则会产生ClassCastException错误。使用当前Properties实现时,只要您不使用Hashtable<Object,Object>的超级Properties中的可变调用方法,就不太可能发生这种情况。

因此,如果不使用您的Properties实例做出令人讨厌的事情,那么这就是您的选择。

答案 2 :(得分:30)

您可以使用Google Guava&#39>:

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

答案 3 :(得分:26)

这个怎么样?

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

会引发警告,但无需迭代即可。

答案 4 :(得分:21)

Java 8方式:

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

答案 5 :(得分:15)

Properties实施Map<Object, Object> - 而不是Map<String, String>

您正在尝试调用此构造函数:

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

...将KV都设为String

Map<Object, Object>不是Map<? extends String, ? extends String> ...它可以包含非字符串键和值。

这样可行:

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

......但它对你没那么有用。

从根本上说,Properties永远不应该成为HashTable的子类......这就是问题所在。从v1开始,它始终能够存储非String键和值,尽管这是违背意图的。如果使用了合成,那么API可以使用字符串键/值,并且一切都会很好。

你可能想要这样的东西:

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

答案 6 :(得分:7)

我会使用以下Guava API: com.google.common.collect.Maps#fromProperties

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

答案 7 :(得分:6)

如果知道您的Properties对象只包含<String, String>条目,则可以使用原始类型:

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

答案 8 :(得分:4)

问题在于Properties实现了Map<Object, Object>,而HashMap构造函数需要Map<? extends String, ? extends String>

This answer解释了这个(非常反直觉的)决定。简而言之:在Java 5之前,Properties实现了Map(因为当时没有泛型)。这意味着您可以将任何 Object放入Properties对象中。 This is still in the documenation:

  

由于Properties继承自HashtableputputAll方法   可以应用于Properties对象。它们的用途很强烈   不鼓励,因为他们允许调用者插入其键或键的条目   值不是String s。应该使用setProperty方法。

为了保持与此的兼容性,设计人员别无选择,只能让它在Java 5中继承Map<Object, Object>。这是一个令人遗憾的结果,即努力实现完全向后兼容性,这使得新代码不必要地复杂化。

如果您只在Properties对象中使用字符串属性,那么应该能够在构造函数中使用未经检查的强制转换:

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

或没有任何副本:

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

答案 9 :(得分:2)

这只是因为HashMap的构造函数需要一个Map泛型类型的arg,而Properties实现了Map。

这会有效,但有警告

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

答案 10 :(得分:1)

您可以使用此:

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

props.forEach((key, value) -> map.put(key.toString(), value.toString()));

答案 11 :(得分:0)

首先,

  

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

HashMap类中没有这样的构造函数,它接受一个属性对象并返回一个hashmap对象。所以你所做的不正确。您应该能够将属性对象强制转换为哈希表引用。

答案 12 :(得分:0)

我用这个:

for (Map.Entry<Object, Object> entry:properties.entrySet()) {
    map.put((String) entry.getKey(), (String) entry.getValue());
}

答案 13 :(得分:0)

当我看到Spring框架源代码时,我找到了这种方式

Properties props = getPropertiesFromSomeWhere();
 // change properties to map
Map<String,String> map = new HashMap(props)