2012-06-01 20 views
9

Ho incontrato lo stesso problema che molte persone sembrano dover affrontare da PHP, la mancanza di una soluzione array associativa decente e facile da usare. Qui ho letto quesioni che fondamentalmente tutte suggerivano di usare una HashMap, come questa Q: Java associative-arrayArray associativi e Java

Tuttavia, non penso che le soluzioni menzionate risolveranno il mio problema. Spiegherò.

Ho una lista con 250 articoli (paesi) per i quali voglio memorizzare i dati. I dati sono di lunghezza indefinita, il che significa che può contenere più voci per "colonna", a volte nessuna voce, a volte 4, eccetera.

in PHP ho potuto solo fare questo:

$country_data = new array(); 
$country_data["nl"]["currency"] = "euro"; 
$country_data["nl"]["languages"] = "Dutch"; 
... 
$country_data["us"]["currency"] = "US dollar"; 
$country_data["us"]["languages"] = array("English", "Spanish"); 

Così a volte mi desidera memorizzare una matrice, a volte no. Ovviamente potrebbe anche essere un array con una sola voce invece di una stringa, ma sto solo dicendo.

Quindi, la domanda è: come posso archiviare e recuperare gli array negli array in una HashMap? Capisco che sono praticamente bloccato con la brutta soluzione di HashMap, ma non riesco ancora a vedere come questo mi consenta di archiviare gli array, sono sicuro di trascurare qualcosa di semplice. Un esempio basato sul mio sarebbe fantastico!

UPDATE

ho optato per andare per HashMaps di HashMaps La ragione di questo ho bisogno di essere in grado di sorvegliare tutto facilmente e modificare poche righe di valori quando necessario. E questo è flessibile, posso facilmente ottenere il nome di un paese in base al codice del paese, una lingua, oppure posso ottenere la HashMap country_data quando ne ho bisogno, o tutti i nomi dei paesi, eccetera.

public class iso_countries { 
    Map<String, Object> country_data  = new HashMap<String, Object>(); 
    Map<String, String> country_name  = new HashMap<String, String>(); 
    Map<String, String[]> country_idd  = new HashMap<String, String[]>(); 
    Map<String, String[]> country_cid  = new HashMap<String, String[]>(); 

    public iso_countries(){  
     country_name.put("nl",   "Netherlands");  
     country_idd.put("nl",  new String[]{"+31"}); 
     country_cid.put("nl",  new String[]{"#31#", "*31#"}); 
     setData(country_name, country_cid, country_idd); 
     // 249 * 4 lines more and later... 
    }//end method 

    public void setData(Map country_name, Map country_cid, Map country_idd){ 
     country_data.put("name", country_name); 
     country_data.put("idd", country_idd); 
     country_data.put("cid", country_cid); 
    }//end method 

    public String getCountryName(String countryCode){ 
     String name  = country_name.get(countryCode); 
     return name; 
    }//end method 

    public String[] getCountryIdd(String countryCode){ 
     String prefix[] = country_idd.get(countryCode); 
     return prefix; 
    }//end method 

    public String[] getCountryCid(String countryCode){ 
     String cid[] = country_cid.get(countryCode); 
     return cid; 
    }//end method 
}//end class 
+0

Si desidera un comportamento simile a hashmap in php o si sta implementando il codice in java? –

+3

Perché i tuoi elenchi hanno codici paese e indici? '$ Country_data [" us "]' funziona perfettamente? –

+1

solo per commentare il tuo codice PHP: non ha nemmeno senso, che i tipi di valore nell'indice ''language'' possono essere totalmente diversi, una volta una stringa, una volta un array ... dovresti decidere quale preferisci, e attenersi ad esso. I tipi di missaggio indicano una pratica di codifica davvero scadente, che rende il tuo codice erratico. EDIT: @Brendan Long: sì, anche questo è un buon avviso. – Sk8erPeter

risposta

8

È possibile memorizzare le matrici come valori di una HashMap:

HashMap<Integer,String[]> hm = new HashMap<Integer,String[]>(); 
hm.put(1, new String[]{ "a", "b" }); 

Per quanto riguarda ad avere tasti "multidimensionali", si può sempre avvolgere insieme con una classe. Un'altra soluzione, seppur brutta, sarebbe quella di avere HashMap s di HashMap s.

+1

Se le chiavi sono numeri interi consecutivi, perché non utilizzare un array o un elenco piuttosto che una mappa? –

+0

grazie, ho scelto questa come soluzione. In realtà ho optato per la soluzione brutta e sto usando HashMaps di HashMaps. Pubblicherò il mio codice più tardi e spiegherò. – slinden77

12

forse sto equivoco il tuo problema, ma perché non creare il proprio oggetto per contenere i dati, quindi memorizzare quelli del HashMap?

Java è un linguaggio orientato agli oggetti, quindi perché non utilizzare la sua struttura più famosa: gli oggetti!

+4

Forse perché dopo anni di esperienza in Java puoi imparare PHP e scoprire che gli array associativi sono gli oggetti che hai sempre cercato. Sono molto più interessanti, perché basta riempirle direttamente da un database e accedervi direttamente nella GUI. Non sono necessari modelli di dati Java, quindi almeno il 20% di lavoro in meno. Hai cambiato il tuo database dei fori? Nessun problema, la tua vecchia GUI Java viene ancora eseguita se utilizza array associativi. Hai solo bisogno di riempire gli stessi array dal nuovo database. Alla fine si tratta di creare array di mappe hash invece di mappe hash di oggetti come hai proposto. La programmazione è un'arte. ;) – Marcus

+0

sì, è solo molto più lavoro per ottenere qualcosa di così semplice – slinden77

+0

@Marcus è una buona osservazione. Non ci avevo pensato prima. – kevin628

11

Un array in PHP è in realtà un hash, non un array.

La cosa corretta da utilizzare in Java è una HashMap. Puoi anche memorizzare valori multpile in un Hashmap memorizzando array o liste al suo interno. Quindi HashMap<String, HashMap<String, Object> o Hashmap<String, List<Object>> potrebbe aiutarti.

Quando si utilizzano array multidimensionali, è necessario utilizzare numeri interi come chiave.

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

ora invece di matrice si inserisce l'elenco, in casi normali si inserirà semplicemente String come valore.

Un altro approccio sarà utilizzare l'oggetto valore che memorizza tutto ciò che è stato assegnato.

public class ValueObject { 

    private Map<String, List<Object>> dataHolder = null; //getter, setter 
} 

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

Il modo corretto è quello di utilizzare un oggetto Paese:

class Country { 
    // Might want these private with getters and/or setters 
    public String currency; 
    public Set<String> languages; 

    // String...languages is like String[] languages, except you can pass the 
    // arguments in like new Country("Euro", "Dutch", "German") 
    // instead of new Country("Euro", new String[] { "Dutch", "German" }) 
    // It's purely stylistic 
    public Country(String currency, String... languages) { 
     this.currency = currency; 
     this.languages = new HashSet<String>(); 
     for(String language : languages) { 
      this.languages.add(language); 
     } 
     // or this.languages = new HashSet<String>(Arrays.asList(languages)); 
    } 
} 

void someFunction() { 
    Map<String, Country> countries = new HashMap<String, Country>(): 
    countries.put("us", new Country("US Dollar", "English", "Spanish")); 
    countries.put("nl", new Country("Euro", "Dutch")); 
} 

Si potrebbe fare questo con l'annidamento elenchi e mappe, per il motivo per cui usare Java se non avete intenzione di utilizzare gli strumenti del compilatore ti dà?

+1

Questa è l'idea giusta. Suggerirei che il campo membro 'lingue' sia 'Set ' o 'Lista ' piuttosto che un array. Nel costruttore, è possibile scorrere le lingue arg per aggiungerli al set uno alla volta oppure usare 'Arrays.toList()'. –

1

In alternativa, se tutte le informazioni su paesi, valute e lingue può essere definito in modo statico, si potrebbe mettere tutto ciò che in una serie di enumerazioni:

public enum Language { 
    EN, ES, FR; 
} 

public enum Currency { 
    USD, GBP, CAD; 
} 

public enum Country { 

    US(USD, EN), UK(GBP, EN), CAN(CAD, EN, FR); 

    private final Language[] languages; 
    private final Currency currency; 

    Country(Currency currency, Language... languages) { 
     this.currency = currency; 
     this.languages = Arrays.copyOf(languages, languages.length); 
    } 

    public Currency getCurrency() { 
     return this.currency; 
    } 

    public Collection<Language> getLanguages() { 
     return asList(this.languages); 
    } 
} 

allora si potrebbe facilmente fare qualcosa di simile:

Map<Integer, Country> data = new HashMap<Integer, Country>(); 
data.put(0, US); 
data.put(1, UK); 

Currency currency = data.get(0).getCurrency(); 
Collection<Language> langs = data.get(0).getLanguages(); 

System.out.println(currency); 
System.out.println(langs); 
Problemi correlati