Properties properties = new Properties();
Map<String, String> map = new HashMap<String, String>(properties);// why wrong?
java.util.Properties
é uma implementação de java.util.Map
, java.util.HashMap
o construtor de And recebe um Map
parâmetro de tipo. Então, por que ele deve ser convertido explicitamente?
Hashtable<Object, Object>
, até mesmo coisas que não sejam strings - até mesmo chaves que não sejam strings.A maneira eficiente de fazer isso é lançar para um mapa genérico da seguinte maneira:
Properties props = new Properties(); Map<String, String> map = (Map)props;
Isso converterá um
Map<Object, Object>
em um mapa bruto, que é "ok" para o compilador (apenas aviso). Assim que tivermos um raw,Map
ele será lançado para oMap<String, String>
qual também estará "ok" (outro aviso). Você pode ignorá-los com anotações@SuppressWarnings({ "unchecked", "rawtypes" })
Isso funcionará porque na JVM o objeto não tem realmente um tipo genérico. Tipos genéricos são apenas um truque que verifica as coisas em tempo de compilação.
Se alguma chave ou valor não for uma String, ocorrerá um
ClassCastException
erro. Com aProperties
implementação atual, é muito improvável que isso aconteça, contanto que você não use os métodos de chamada mutáveis do superHashtable<Object,Object>
deProperties
.Portanto, se não fizer coisas desagradáveis com sua instância de Propriedades, este é o caminho a seguir.
fonte
Map
instância pelo menos no código fornecido, então pensei que isso é o que ele precisaVocê pode usar o Google Guava's:
com.google.common.collect.Maps.fromProperties (Propriedades)
fonte
Que tal agora?
Map properties = new Properties(); Map<String, String> map = new HashMap<String, String>(properties);
Irá causar um aviso, mas funciona sem iterações.
fonte
Map<Object, Object>
, é umMap
argumento (tipo bruto). Esta resposta está correta(Map<String, String>) ((Map) properties)
O método Java 8:
fonte
Properties
implementosMap<Object, Object>
- nãoMap<String, String>
.Você está tentando chamar este construtor:
public HashMap(Map<? extends K,? extends V> m)
... com
K
eV
ambos comoString
.Mas
Map<Object, Object>
não éMap<? extends String, ? extends String>
... pode conter chaves e valores que não sejam de string.Isso funcionaria:
Map<Object, Object> map = new HashMap<Object, Object>();
... mas não seria tão útil para você.
Fundamentalmente,
Properties
nunca deveria ter sido feita uma subclasse deHashTable
... esse é o problema. Desde v1, ele sempre foi capaz de armazenar chaves e valores não String, apesar de ser contra a intenção. Se a composição tivesse sido usada em vez disso, a API poderia ter funcionado apenas com chaves / valores de string e tudo estaria bem.Você pode querer algo assim:
Map<String, String> map = new HashMap<String, String>(); for (String key : properties.stringPropertyNames()) { map.put(key, properties.getProperty(key)); }
fonte
Properties<String,String> properties = new Properties<String,String>();
. Peculiar.Properties
si não é genérico.Eu usaria a seguinte API Guava: com.google.common.collect.Maps # fromProperties
Properties properties = new Properties(); Map<String, String> map = Maps.fromProperties(properties);
fonte
Se você sabe que seu
Properties
objeto contém apenas<String, String>
entradas, pode recorrer a um tipo bruto:Properties properties = new Properties(); Map<String, String> map = new HashMap<String, String>((Map) properties);
fonte
O problema é que
Properties
implementaMap<Object, Object>
, enquanto oHashMap
construtor espera umMap<? extends String, ? extends String>
.Essa resposta explica essa decisão (bastante contra-intuitiva). Resumindo: antes do Java 5,
Properties
implementadoMap
(já que não havia genéricos naquela época). Isso significa que você pode colocar qualquerObject
um em umProperties
objeto. Isso ainda está na documentação:Para manter a compatibilidade com isso, os designers não tiveram outra escolha a não ser fazer com que ele herdasse
Map<Object, Object>
em Java 5. É um resultado infeliz do esforço para obter compatibilidade total com versões anteriores, o que torna o novo código desnecessariamente complicado.Se você sempre usa propriedades de string em seu
Properties
objeto, deverá conseguir fazer uma conversão não verificada em seu construtor:Map<String, String> map = new HashMap<String, String>( (Map<String, String>) properties);
ou sem quaisquer cópias:
fonte
public HashMap(Map<? extends K, ? extends V> m)
. Ele não espera umMap<String, String>
Map<Object, Object>
não pode ser usado para um argumento formal do tipo `Map <? extends String,? extends String> `.isso ocorre apenas porque o construtor de HashMap requer um argumento do tipo genérico Map e Properties implementa Map.
Isso funcionará, embora com um aviso
Properties properties = new Properties(); Map<String, String> map = new HashMap(properties);
fonte
Você pode usar isto:
Map<String, String> map = new HashMap<>(); props.forEach((key, value) -> map.put(key.toString(), value.toString()));
fonte
Primeira coisa,
Não existe tal construtor na classe HashMap que pega um objeto de propriedades e retorna um objeto hashmap. Portanto, o que você está fazendo NÃO é correto. Você deve ser capaz de converter o objeto de propriedades para referência de hashtable.
fonte
Eu uso isso:
for (Map.Entry<Object, Object> entry:properties.entrySet()) { map.put((String) entry.getKey(), (String) entry.getValue()); }
fonte