2009-08-28 9 views
55

Così ho due domande su HashMap s in Java:Modo corretto per inizializzare HashMap e HashMap può contenere diversi tipi di valore?

  1. Qual è il modo corretto per inizializzare un HashMap? Penso che potrebbe essere meglio nella mia situazione da usare:

    HashMap x = new HashMap(); 
    

    Ma Eclipse di continuo suggerendo che io uso:

    HashMap<something, something> map = new HashMap(); 
    

    Che è meglio?

  2. Un HashMap può contenere diversi tipi di oggetti/tipi di dati come valori? Ad esempio, sarebbe questo lavoro ed essere OK:

    map.put("one", 1); 
    map.put("two", {1, 2}); 
    map.put("three", "hello"); 
    

    Nella prima put(), voglio una int come valore, nel secondo un int[], e la terza una stringa. Va bene farlo in Java con HashMap s? Inoltre, va bene memorizzare un valore HashMap come valore all'interno di HashMap?

risposta

91

Dipende molto dal tipo di sicurezza di cui avete bisogno.Il modo non generico di farlo è meglio farlo come:

Map x = new HashMap(); 

noti che x viene data come Map. questo rende molto più facile cambiare le implementazioni (a TreeMap o a LinkedHashMap) in futuro.

È possibile utilizzare farmaci generici per garantire un certo livello di sicurezza di tipo:

Map<String, Object> x = new HashMap<String, Object>(); 

In Java 7 e versioni successive si può fare

Map<String, Object> x = new HashMap<>(); 

È possibile che, mentre più prolisso, evita avvisi del compilatore. In questo caso il contenuto di HashMap può essere qualsiasi Object, quindi può essere Integer, int[], ecc. Che è ciò che si sta facendo.

Se si sta ancora utilizzando Java 6, Guava Libraries (anche se è abbastanza facile da fare da soli) ha un metodo chiamato newHashMap() che evita la necessità di duplicare le informazioni generiche digitazione quando si esegue una new. Indisce il tipo dalla dichiarazione della variabile (questa è una funzionalità Java non disponibile sui costruttori precedenti a Java 7).

A proposito, quando si aggiunge un'int o altra primitiva, Java lo sta attivando automaticamente. Ciò significa che il codice è equivalente a:

x.put("one", Integer.valueOf(1)); 

Si può certamente mettere un HashMap come un valore in un altro HashMap, ma penso che ci sono problemi se lo si fa in modo ricorsivo (che è mettere il HashMap come un valore in si).

+0

Qual è la differenza tra fare una HashMap map = new ... e Map map = new ...? O fanno la stessa cosa? – sepiroth

+3

Fanno la stessa cosa, è solo che il tuo riferimento viene digitato come una mappa (l'interfaccia) invece di HashMap (l'implementazione) in modo che l'implementazione possa essere facilmente modificata senza influenzare più di una riga di codice. – Yishai

4

Eclipse consiglia di dichiarare il tipo di HashMap perché impone un certo tipo di sicurezza. Certo, sembra che tu stia cercando di evitare la sicurezza del tipo dalla tua seconda parte.

Se si desidera eseguire quest'ultimo, provare a dichiarare la mappa come HashMap<String,Object>.

+0

è un int considerato un oggetto..? – sepiroth

+0

"int" s non sono oggetti, è un tipo primitivo. Tutti i primitivi (int, double, long, short ...) hanno una versione oggetto che puoi usare (Integer, Double, Long, Short). Java 1.5+ eseguirà anche la conversione tra int e Integer per te, quindi non devi preoccuparti di ciò (il più delle volte, cerca "autoboxing"). – MBCook

+0

autoboxing convertirà int [] in un oggetto. –

1

Una HashMap può contenere qualsiasi oggetto come valore, anche se è un'altra HashMap. Eclipse suggerisce di dichiarare i tipi perché questa è la pratica consigliata per le raccolte. sotto Java 5. Sei libero di ignorare i suggerimenti di Eclipse.

Sotto Java 5, un int (o qualsiasi tipo primitivo) sarà autoboxed in un numero intero (o un altro tipo corrispondente) quando lo si aggiunge a una raccolta. Fai attenzione, però, perché ci sono alcuni punti fermi nell'utilizzo dell'autoboxing.

12

Questa è una modifica apportata con Java 1.5. Quello che elencherai prima è il vecchio modo, il secondo è il nuovo modo.

Utilizzando HashMap si possono fare cose come:

HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>(); 

.... 

Doohickey result = ourMap.get("bob"); 

Se non hai avuto i tipi sulla mappa, dovreste fare questo:

Doohickey result = (Doohickey) ourMap.get("bob"); 

E 'davvero molto utile. Ti aiuta a catturare bug ed evitare di scrivere ogni tipo di cast extra. Era una delle mie funzionalità preferite di 1.5 (e più recente).

È ancora possibile inserire più oggetti nella mappa, basta specificarlo come Mappa, quindi è possibile inserire qualsiasi oggetto (una stringa, un'altra mappa e numero intero e tre oggetti personali se si è così inclini).

+2

Mi hai avuto fino all'ultimo paragrafo. "gli elenchi con poca 'l'" sono chiamati array; e sono sicuramente oggetti in Java. – ChssPly76

+0

Hai detto che per mettere più cose sulla mappa, dovrei semplicemente specificarlo come una mappa. Perché non potrei usare HashMap? – sepiroth

+0

@ ChssPly76: "array". Questo è il termine. Non riuscivo a ricordarlo e sono andato con la mia ipotesi migliore al momento. Grazie. – MBCook

0

In risposta alla seconda domanda: Sì, una HashMap può contenere diversi tipi di oggetti. Che sia una buona idea o meno dipende dal problema che stai cercando di risolvere.

Detto questo, il tuo esempio non funzionerà. Il valore int non è un oggetto. Devi usare la classe Integer wrapper per memorizzare un valore int in un HashMap

+0

In Java 5+, il compilatore lo farà per te. – Yishai

+0

Funzionerà in Java 5, che sta utilizzando dal momento che sta ricevendo avvisi per non aver parametrizzato la mappa, con autoboxing. – ColinD

3

Il modo in cui si sta scrivendo è equivalente a

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

cosa va all'interno delle parentesi è comunicando al compilatore che cosa inserirai la HashMap in modo che possa eseguire il controllo degli errori per te. Se Object, Object è ciò che realmente vuoi (probabilmente no) dovresti dichiararlo esplicitamente. In generale, dovresti essere il più esplicito possibile con la dichiarazione per facilitare il controllo degli errori da parte del compilatore. Quello che hai descritto dovrebbe probabilmente essere dichiarato in questo modo:

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

In questo modo almeno dichiara che le chiavi stanno per essere stringhe, ma i valori possono essere qualsiasi cosa. Ricordati di usare un cast quando ottieni un valore.

2

Il 2 ° utilizza generici forniti con Java 1.5. Ridurrà il numero di cast nel tuo codice & può aiutarti a catturare errori in compiletime invece che in runtime. Detto questo, dipende da cosa stai codificando. Una mappa sporca di & sporca per contenere alcuni oggetti di vario tipo non ha bisogno di generici. Ma se la mappa contiene oggetti che discendono da un tipo diverso da Object, può valerne la pena.

Il poster precedente non è corretto sull'array in una mappa. Un array è in realtà un oggetto, quindi è un valore valido.

Map<String,Object> map = new HashMap<String,Object>(); 
map.put("one",1); // autoboxed to an object 
map.put("two", new int[]{1,2}); // array of ints is an object 
map.put("three","hello"); // string is an object 

Inoltre, poiché HashMap è un oggetto, può anche essere un valore in una HashMap.

+0

ma come ottengo tutti i valori che ho in HashMap ????? – Ads

1

Eclipse suggerisce di definire generic type in modo da poter avere type safety. È possibile scrivere

Map m = new HashMap(); 

che non garantisce la sicurezza di tipo ma seguente sarà garantire la sicurezza di tipo

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

Il Object può essere di qualsiasi tipo come String, Integer ecc