2011-01-15 21 views
10

Ho due mappe che contengono lo stesso tipo di oggetti:Unione di due o più (hash) mappe

Map<String, TaskJSO> a = new HashMap<String, TaskJSO>(); 
Map<String, TaskJSO> b = new HashMap<String, TaskJSO>(); 

public class TaskJSO { String id; } 

Le chiavi della mappa sono le proprietà "ID".

a.put(taskJSO.getId(), taskJSO); 

voglio ottenere un elenco con: tutti i valori nella "mappa B" + tutti i valori "Mappare" che non sono in "mappa B".

Che cos'è il modo più veloce per eseguire questa operazione?

Grazie

EDIT: Il comparaison è fatto da id. Quindi, due TaskJSO sono considerati uguali se hanno lo stesso id (il metodo equals è sovrascritto).

La mia intenzione è sapere qual è il modo più veloce per eseguire questa operazione dal punto di vista delle prestazioni. Per esempio, c'è qualche differenza se faccio il "comparaison" in una mappa (come suggerito da Peter):

Map<String, TaskJSO> ab = new HashMap<String, TaskJSO>(a); 
ab.putAll(b); 
ab.values() 

o se invece io uso un set (come suggerito da Nishant):

Set s = new Hashset(); 
s.addAll(a.values()); 
s.addAll(b.values()); 
+0

Probabilmente dipende dall'implementazione Java che si sta utilizzando. – Thomas

+0

Una mappa 'id' su un' TaskJSO' in Map 'a' e un diverso' TaskJSO' in Map 'b'? – dkarp

+0

@dkarp si, uno stesso id può mappare a due diversi TaskJSO in Map a e Map b (memorizzano diverse versioni di una stessa entità) –

risposta

11

Metodo 1:

Set s = new HashSet(); 
s.addAll(a.values()); 
s.addAll(b.values()); 

Set è collezione di oggetti unici. Fare riferimento: http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashSet.html


Metodo 2:

This sarà confrontare le chiavi, e se si trovano stessi tasti - il valore verrà sovrascritto dal valore più tardi del Map.

Map<String, TaskJSO> ab = new HashMap<String, TaskJSO>(a); 
ab.putAll(b); 
ab.values() 

Ora, non importa qual è il caso ... il confronto si svolgerà utilizzando equals. Quindi, Method-1 chiamerà equals su tutti i valori e Method2 lo chiamerà su tutte le chiavi. A seconda della complessità del confronto, le prestazioni varieranno.

Nel metodo 1, è necessario creare un nuovo Set ma garantisce che non vengano sovrascritti valori diversi con le stesse chiavi. Ma Method-2 è intelligente, se hai ID univoci.

Modifica # 1 aggiornamenti come la questione è stata aggiornata

+0

Ho pensato che l'OP volesse gli elementi in una lista ordinata nell'ordine specificato. Questo approccio può essere adattato per farlo? – templatetypedef

+0

L'OP non indica l'ordine. Ma l'ordine si rovinerà comunque. Per l'elemento comune, quale ordine di set è preferito? Esempio: A: {1,2,3}, B: {2,4,5}, A unione B: {1,2,3,4,5} o {1,3,2,4,5}, B unione A: {2,4,5,1,3} o {4,5,1,2,3}? Voglio dire, faresti meglio a renderlo paragonabile e ordinarlo all'uomo! :) – Nishant

+1

HashMap è una mappa non ordinata. cercare di mantenere un ordine non avrebbe molto senso. –

2

penso che si può fare questo in tempo lineare come segue. Sia n e m il numero di elementi in a e b, rispettivamente.

  1. Creare un nuovo HashSet contenente tutti i valori da b. Il tempo è O (m).

  2. Aggiungere tutti i valori da b a un nuovo elenco. Il tempo è O (m).

  3. Per ciascun valore in a, verificare se lo HashSet di valori in b contiene quell'elemento. Se è così, non fare nulla. Altrimenti, aggiungilo alla lista. Il tempo è O (n).

Questo termina utilizzando non più di O (n + m) tempo, che è lineare.

9

Se si desidera che tutta la chiave/i valori da b più tutti i valori in a, non in b.

Map<String, TaskJSO> ab = new HashMap<String, TaskJSO>(a); 
ab.putAll(b); 

Inizia con una copia di ae sostituisce o aggiunge tutte le chiavi/valori da b.

+0

Non penso che funzionerà. L'op afferma che 'uno stesso id può essere associato a due diversi TaskJSO in Map a e Map b'. Ciò significa che 'ab.putAll (b)' fallirà se 'a' e' b' hanno voci con lo stesso 'id' – ryanprayogo

+2

@ryanprayogo, cosa intendi per errore? 'a' e' b' possono avere le stesse chiavi, putAll() lascerà i valori che erano in 'b' dove ci sono duplicati. –

+0

Scusa, ignora quello che ho detto. Non ho davvero avuto la domanda prima. – ryanprayogo