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


Answers:


86

这是因为PropertiesextendsHashtable<Object, Object>(又实现了Map<Object, Object>)。您尝试将其输入Map<String, String>。因此,它是不兼容的。

您需要将字符串属性一一输入到地图中。

例如:

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

1
是的,但这不是这里的问题:通用参数不匹配。您可以在中输入任意内容Hashtable<Object, Object>,甚至可以输入非字符串的内容,甚至可以输入非字符串的
fge

@assylias:不,也不会编译。
乔恩·斯基特

12
在1,8中可以执行properties.forEach((k,v)-> map.put((String)k,(String)v));
ModdyFire '17

1
或者如果您尚不具备地图属性.entrySet()。stream()。collect(Collectors.toMap(e->(String)e.getKey(),e->(String)e.getValue( )))
Tonicic

46

做到这一点的有效方法只是将其转换为通用Map,如下所示:

Properties props = new Properties();

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

这会将a转换Map<Object, Object>为原始Map,对于编译器来说这是“确定”的(仅警告)。一旦我们有了原始数据Map,它将被转换Map<String, String>为“ ok”(另一个警告)。您可以通过注释忽略它们@SuppressWarnings({ "unchecked", "rawtypes" })

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

如果某些键或值不是字符串,则会产生ClassCastException错误。与目前Properties执行这是非常不可能发生的,只要你不使用可变的调用方法从超Hashtable<Object,Object>Properties

因此,如果不对您的Properties实例进行任何令人讨厌的事情,这就是方法。


问题是要转换为HashMap。没有任何地图。
AlikElzin-kilaka

3
是的,问题标题说的是,但是目标是Map至少在给定的代码上有一个实例,所以我认为这就是他所需要的
Padilo

尽管我喜欢其他纯粹主义者的解决方案,但由于它只是一条简单的线,因此该解决方案对我来说很方便。
阿方索西川


27

这个怎么样?

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

将引起警告,但无需迭代即可工作。


4
@fge:不是a Map<Object, Object>,而是Map参数(原始类型)。这个答案是正确的
Lukas Eder 2013年

2
嗯,是的,我尝试了Eclipse。Eclipse和javac之间的那些通用差异之一?....不,也可以使用javac
Lukas Eder

4
这可行,但是迭代仍然会发生。如果查看HashMap的源代码,则构造函数基本上会遍历泛型map参数。因此计算时间不会改变,但是代码肯定更简洁。
Simeon G

如前面的回答所述,无需创建新实例并遍历properties对象。只需使用一系列转换即可: (Map<String, String>) ((Map) properties)
里卡多·韦洛索

22

Java 8方式:

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

有没有一种方法可以使用方法引用代替lambda。声纳库贝问题的Cos。
Viyaan Jhiingade

16

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开始,它始终能够存储非字符串键和值,尽管这违反了意图。如果成分已经代替,该API可以有使用字符串键/值,并且一切都会很好。

您可能想要这样的东西:

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

显然也不可能明确地做Properties<String,String> properties = new Properties<String,String>();。奇特。
2013年

1
@eis这是设计使然,Properties它本身不是通用的。
Mattias Buelens

我宁愿说这是不幸的一系列选择,而不是设计,但是,是的。
2013年

2
@eis:不,是设计使Properties成为字符串到字符串映射。这不是通用的,这是有道理的。它没有任何意义,你可以添加非字符串键/值。
乔恩·斯基特


8

如果你知道你的Properties对象仅包含<String, String>条目,可以求助于原始类型:

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

4

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

这个答案解释了这个(相当违反直觉的)决定。简而言之:在Java 5之前Properties实现Map(因为那时没有泛型)。这意味着你可以把任何 Object一个Properties对象。这仍然是文档:

由于Properties继承自HashtableputandputAll方法可以应用于Properties对象。不鼓励使用它们,因为它们允许调用方插入键或值不是Strings的条目。setProperty应该改用该方法。

为了保持这种兼容性,设计人员别无选择,只能使其Map<Object, Object>在Java 5中继承。这是努力实现向后兼容性的不幸结果,这种兼容性使不必要的新代码复杂化。

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

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

或无任何副本:

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

这是HashMap构造函数的签名public HashMap(Map<? extends K, ? extends V> m)。没想到Map<String, String>
Mubin

@Mubin好的,我对此事简化了一些。尽管如此,该参数仍然成立:aMap<Object, Object>不能用于Map <?类型的形式参数。扩展String,?扩展String>`。
Mattias Buelens

2

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

这将起作用,尽管有警告

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

1

您可以使用此:

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

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

0

第一件事

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

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


0

我用这个:

for (Map.Entry<Object, Object> entry:properties.entrySet()) {
    map.put((String) entry.getKey(), (String) entry.getValue());
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.