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

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

java.util.Properties是Map的一个实现,而HashMap的构造函数接收一个Maptypes的参数。 但为什么要明确转换?

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

您需要将string属性逐个送入您的地图…

例如:

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

这个怎么样?

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

会导致警告,但没有重复的工作。

要做到这一点的有效方法只是投射到一个通用的地图如下:

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

这将把一个Map<Object, Object>转换为一个原始的Map,编译器(只有警告)为“ok”。 一旦我们有一个原始的Map ,它将投影到Map<String, String> ,它也将是“好”(另一个警告)。 你可以通过注释@SuppressWarnings({ "unchecked", "rawtypes" })忽略它们。

这将工作,因为在JVM中,该对象实际上并不具有genericstypes。 genericstypes只是在编译时validation事物的一个技巧。

如果某个键或值不是一个string,它将产生一个ClassCastException错误。 使用当前的Properties实现,这是不太可能发生的,只要你不使用Properties的超级Hashtable<Object,Object>中的可变调用方法。

所以,如果不用你的Properties实例做一些令人讨厌的事情,这就是要走的路。

你可以使用Google Guava的:

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

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<? extends String, ? extends String> Map<? extends String, ? extends String> …它可以包含非string键和值。

这将工作:

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

…但它不会对你有用。

从根本上说, Properties不应该成为HashTable的子类…这就是问题所在。 从v1开始,它始终能够存储非string键和值,尽pipe这是违背意图的。 如果已经使用了组合,API可能只能使用string键/值,并且一切都会好的。

你可能想要这样的东西:

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

Java 8的方式:

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

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

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

问题是Properties实现Map<Object, Object> ,而HashMap构造函数需要一个Map<? extends String, ? extends String> Map<? extends String, ? extends String> Map<? extends String, ? extends String>

这个答案解释了这个(非常直观的)决定。 简而言之:在Java 5之前, Properties实现了Map (因为当时没有generics)。 这意味着你可以把任何 Object放在Properties对象中。 这仍然是在文件中:

由于PropertiesHashtableinheritance, putputAll方法可以应用于Properties对象。 强烈build议不要使用它们,因为它们允许调用者插入其键或值不是String的条目。 应该使用setProperty方法。

为了保持兼容性,devise人员没有别的select,只能inheritanceJava 5中的Map<Object, Object> 。这是一个不幸的结果,它致力于完全向后兼容,这使得新代码不必要的复杂化。

如果你只在你的Properties对象中使用过string属性,你应该可以在构造函数中使用未经检查的强制转换:

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

或没有任何副本:

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

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

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

这只是因为HashMap的构造函数需要一个Mapgenericstypes的属性和Properties实现Map。

这将工作,但有警告

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

首先,

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

HashMap类中没有这样的构造函数,它需要一个属性对象并返回一个HashMap对象。 所以你在做什么是不正确的。 您应该能够将属性的对象转换为散列表引用。