2015-09-29 10 views
5

i dati raccolti qualcosa comeUn ArrayList creato da keySet() di LinkedHashMap conserva l'ordine di inserimento?

{ "Dipendente 1 della ABC", "ABCX"}, { "Dipendente 2 di ABC", "ABCY"}, { "Dipendente 3 della ABC", "ABCZ "}

dal database tramite un RefCursor.

Ho un caso in cui ho bisogno di conservare l'ordine in cui i dati vengono letti dal database. Poiché i miei dati sono una specie di "valore-chiave", ho pensato di utilizzare un'implementazione di Map ordinata. Quindi scelto LinkedHashMap

//defined as a static map inside a common utlity class 
public class Common{ 
public static final LinkedHashMap<String, String> empMap = new LinkedHashMap<String, String>(); 
} 

//rs is the resultset 
if (rs != null) { 
      while (rs.next()) { 
       key = rs.getString("name_text"); 
       value = rs.getString("id"); 
       Common.empMap.put(key, value); 
      } 
} 

devo passare le chiavi al cliente, nello stesso ordine in cui sono stati recuperati dal database (cursore).

List<String> empList = new ArrayList<String>(Common.empMap.keySet()); 

keySet() -. La documentazione dice "restituisce una visione Set delle chiavi contenute in questa mappa Il set è sostenuta dalla mappa, in modo da modificare la mappa si riflettono nel set, e viceversa"

mi aspetto è che Da ArrayList è anche un insieme ordinato, devo avere le chiavi nello stesso modo in cui è stato recuperato/inserito nel Map.

Quando eseguo un programma di prova di esempio, si ottiene come previsto.

public class LinkedMap {  
    public static void main(String[] args) { 
     LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();   
     map.put("Employee 1 of ABC", "ABCX"); 
     map.put("Employee 2 of ABC", "ABCY"); 
     map.put("Employee 3 of ABC", "ABCZ"); 
     ArrayList<String> list = new ArrayList<String>(map.keySet()); 
     System.out.println(list); 
    } 
} 

uscita: [Impiegato 1 di ABC, Impiegato 2 di ABC, Impiegato 3 di ABC]

Tuttavia il mio domanda è, se questo è garantito uscita o è che io ricevo solo casualmente, e potrebbe variare,

Update (?): 2015/09/30

Grazie a tutti, ognuno di voi ha contribuito con punti validi.

In sintesi tutte le risposte,

E 'garantito che l'ordine è mantenuto.

Secondo Javadocs,

LinkedHashMap è tabella hash e attuazione lista collegata dell'interfaccia Map , con ordine di iterazione prevedibile. Questa implementazione differisce da HashMap in quanto mantiene una lista doppiamente collegata che esegue attraverso tutte le sue voci.Questa lista collegata definisce l'iterazione ordinamento, che normalmente è l'ordine in cui le chiavi sono state inserite mappa (inserimento-ordine)

cioè: LinkedHashMap itererà nell'ordine in cui le voci sono state messe in la mappa.

Quindi LinkedHashMap#keySet() mi darà lo stesso ordine in cui sono state inserite le chiavi sulla mappa, perché lo LinkedHashMap#keySet().iterator() itera nell'ordine specificato.

Andando in profondità per l'attuazione di iterator() possiamo vedere che,

LinkedHashMap implementa il metodo newKeyIterator(), che restituisce un'istanza di una classe che eredita LinkedHashIterator, curando l' 'ordinazione'

// These Overrides alter the behavior of superclass view iterator() methods 
Iterator<K> newKeyIterator() { return new KeyIterator(); } ... 

private class KeyIterator extends LinkedHashIterator<K> {... 

private abstract class LinkedHashIterator<T> implements Iterator<T> { ... 

per questo: ArrayList<String> list = new ArrayList<String>(map.keySet()); il costruttore ArrayList (Collection) è documented per riempire la lista nell'ordine in cui eleme i nts vengono restituiti dall'iteratore della Collection specificato.

+0

Mi piace come il tipo di variabile sia il più specifico 'LinkedHashMap', invece di una vaga' Mappa' :) – ZhongYu

+0

Penso che avere l'interfaccia o il riferimento di classe concreto non faccia la differenza nel mio caso d'uso. Ma devo ammettere che è stato un errore usare la classe concreta piuttosto che l'interfaccia. O ti senti diverso? – spiderman

+0

no, penso che sia meglio usare il tipo più specifico per le variabili locali/di istanza. – ZhongYu

risposta

4

E è garantito.

Anche se l'interfaccia Set di per sé non garantisce alcun ordine (o meglio, LinkedHashSet fa), il fatto che l'attuazione Map si garantisce l'inserimento di ordinare praticamente garantisce che si ottengono le chiavi in ​​questo ordine pure. L'interfaccia restituita da .keySet() è semplicemente una Set in quanto, beh, le chiavi in ​​un Map sono garantite come uniche.

Se non fosse, si consideri che cosa accadrebbe in questa situazione:

// case 1 
for (final Map.Entry<K, V> entry: map.entrySet()) { 
    // entry.getKey(), entry.getValue() 
} 

// case 2 
for (final K key: map.keySet()) { 
    V value = map.get(key); 
} 

Se questi due codici avevano due comportamenti differenti, uh ...

+0

Grazie +1, "L'interfaccia restituita da .keySet() sembra essere un Set" - il pensiero di questo "Set" era quello che mi confondeva – spiderman

+0

Non capisco il tuo punto sul confronto tra i due codici :( – spiderman

+0

Beh, cosa succede se quei due pezzi di codice sono ripetuti in un ordine diverso? O anche .values ​​()? – fge

2

Sì, è garantito.

In Oracle JDK, la classe LinkedHashMap reimplement il metodo newKeyIterator() che restituisce un'istanza di una classe che eredita LinkedHashIterator. Quello è ordinato.

+0

molto valido, +1 mi sono tuffato in esso per vederlo :) – spiderman

1

Le altre risposte spiegano che LinkedHashMap#keySet().iterator() itera in ordine specificato, per cui vorrei solo aggiungere:

ArrayList Javadoc dice di ArrayList(Collection):

Costruisce una lista contenente gli elementi della collezione specificato, nel ordina che vengano restituiti dall'iteratore della raccolta.

Quindi è garantito che gli articoli ArrayList saranno nello stesso ordine.

+0

Ho ricevuto grazie +1 – spiderman

1

L'ordine di iterazione di uno LinkedHashSet è garantito essere uguale all'ordine in cui sono inserite le chiavi (supponendo che non si usi il costruttore speciale che consente di richiedere l'ordinamento in base all'accesso più recente). Puoi trovarlo in its documentation.

suppongo che si possa sostenere che la garanzia ordine di iterazione è valida solo per il set di ingresso, non alle altre viste, ma la documentazione non supportano molto bene (in quanto si riferiscono a il iterazione di ordine), e in pratica le viste di raccolta condividono un ordine di iterazione comune.

Da parte sua, il costruttore ArrayList(Collection)is documented per compilare l'elenco nell'ordine in cui gli elementi vengono restituiti dall'iteratore specificato Collection.

1

Come spiegato in questa domanda Does entrySet() in a LinkedHashMap also guarantee order? e annotato nello JavaDocs, le operazioni di tipo di iterazione sono definite nell'ordine di inserimento per LinkedHashMap. Ciò influisce sul keySet come fa il entrySet.

Il costruttore di ArrayList verrà inserito nell'ordine nell'ordine dell'iteratore.

Queste due condizioni combinate indicano che l'API garantisce questo comportamento.

+0

Buona, +1 per i riferimenti – spiderman

Problemi correlati