Подтвердить что ты не робот

Преобразование java.util.Properties в HashMap <String, String>

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

java.util.Properties является реализацией java.util.Map, а конструктор java.util.HashMap получает параметр типа Map. Итак, почему это должно быть преобразовано явно?

4b9b3361

Ответ 1

Это связано с тем, что Properties extends Hashtable<Object, Object> (что, в свою очередь, реализует Map<Object, Object>). Вы пытаетесь передать это в Map<String, String>. Поэтому он несовместим.

Вам нужно передать свойства строки по одному на вашу карту...

Например:

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

Ответ 2

Эффективный способ сделать это - просто привести к общей карте следующим образом:

Properties props = new Properties();

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

Это преобразует Map<Object, Object> в необработанную карту, которая является "ok" для компилятора (только предупреждение). Как только у нас будет сырой Map, он будет отбрасываться на Map<String, String>, который также будет "хорошо" (другое предупреждение). Вы можете игнорировать их с помощью аннотации @SuppressWarnings({ "unchecked", "rawtypes" })

Это будет работать, потому что в JVM объект не имеет общего типа. Родовые типы - всего лишь трюк, который проверяет вещи во время компиляции.

Если какой-либо ключ или значение не является строкой, это приведет к ошибке ClassCastException. При текущей реализации Properties это очень маловероятно, если вы не используете изменяемые методы вызова из супер Hashtable<Object,Object> Properties.

Итак, если вы не делаете неприятные вещи с помощью экземпляра Properties, это способ пойти.

Ответ 4

Как насчет этого?

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

Вызывает предупреждение, но работает без итераций.

Ответ 5

Способ Java 8:

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

Ответ 6

Properties реализует Map<Object, Object> - not Map<String, String>.

Вы пытаетесь вызвать этот конструктор:

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

... с K и V как 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));
}

Ответ 8

Если вы знаете, что ваш объект Properties содержит только записи <String, String>, вы можете прибегнуть к необработанному типу:

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

Ответ 9

Проблема заключается в том, что Properties реализует Map<Object, Object>, тогда как конструктор HashMap ожидает Map<? extends String, ? extends String>.

Этот ответ объясняет это (совершенно противоречивое) решение. Короче: до Java 5, Properties реализовано Map (так как тогда не было никаких дженериков). Это означает, что вы можете поместить любой Object в объект Properties. Это все еще находится в предложении:

Поскольку Properties наследует от Hashtable, методы put и putAllможет применяться к объекту Properties. Их использование сильно обескуражены, поскольку они позволяют вызывающему абоненту вставлять записи, чьи ключи или значения не являются String s. Вместо этого следует использовать метод 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;

Ответ 10

это происходит только потому, что для конструктора HashMap требуется аргумент типа Generic Map и Properties реализует Map.

Это будет работать, хотя с предупреждением

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

Ответ 11

Первое,

Класс свойств основан на Hashtable, а не в Hashmap. Класс свойств в основном расширяет Hashtable

В классе HashMap нет такого конструктора, который принимает объект свойств и возвращает вам объект hashmap. Так что вы делаете НЕ правильно. Вы должны иметь возможность передать объект свойств в хеш-таблицу.

Ответ 12

я использую это:

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