2009-03-11 7 views
6

Nella mia applicazione ho due tipi di oggetti in cui ogni oggetto di un tipo ha esattamente un oggetto corrispondente all'altro tipo.Qualunque svantaggio nell'usare oggetti arbitrari come chiavi Mappa in Java?

La scelta ovvia per tenere traccia di questa relazione è una Map<type1, type2>, come una HashMap. Ma in qualche modo, sono sospettoso. Posso usare un oggetto come chiave nella mappa, passarlo, farlo sedere in un'altra collezione, e recuperare il suo partner dalla mappa in qualsiasi momento?

Dopo che un oggetto è stato creato, tutto quello che sto passando è un identificatore, giusto? Quindi probabilmente non c'è nessun problema lì. Cosa succede se serializzo e deserializza la chiave?

Eventuali altri avvertimenti? Dovrei usare qualcos'altro per mettere in correlazione le coppie di oggetti, come un numero che mi generi?

risposta

22
  1. la chiave deve implementare .equals() e .hashCode() correttamente
  2. La chiave non deve essere modificato in alcun modo che cambia è .hashCode() valore quando viene utilizzato come chiave
  3. Idealmente qualsiasi oggetto utilizzato come chiave in un HashMap dovrebbe essere immutabile. Ciò assicurerebbe automaticamente che 2. sia sempre valido.
  4. Gli oggetti che potrebbero essere GCed potrebbero essere tenuti in giro quando vengono utilizzati come chiave e/o valore.
0

Qualsiasi oggetto può essere una chiave di mappa. La cosa importante qui è assicurarsi di sovrascrivere .equals() e .hashCode() per tutti gli oggetti che verranno utilizzati come chiavi della mappa.

Il motivo per cui lo fai è che, se non lo fai, l'uguaglianza sarà intesa come uguaglianza di oggetti e l'unico modo per trovare chiavi di mappa "uguali" è avere un handle per l'oggetto originale si.

Si esegue l'override di hashcode perché deve essere coerente con gli uguali. Questo è così che gli oggetti che hai definito come hash uguali in modo identico.

0

I punti di errore sono le funzioni hashcode e equals. Se non producono valori di ritorno coerenti e corretti, la Mappa si comporterà in modo strano. Effective Java ha un'intera sezione su di essi ed è altamente raccomandato.

7

ho due tipi di oggetti nella mia applicazione in cui ogni oggetto di uno tipo ha esattamente un corrispondente oggetto dell'altro genere.

Questo suona davvero come una relazione has-a e quindi potrebbe essere implementato utilizzando un semplice attributo.

+0

Sono d'accordo. Il resto della domanda potrebbe ancora essere utile per gli altri, 'comunque. (o anche per @OP se questa non è un'alternativa per qualche motivo) –

+0

@saua sono d'accordo con te. Solo che vorrei sottolineare l'applicabilità degli attributi in questo particolare contesto. –

1

È possibile utilizzare una mappa standard, ma facendo così manterrai forti riferimenti ai tuoi oggetti nella mappa. Se i tuoi oggetti sono referenziati in un'altra struttura e hai bisogno della Mappa solo per collegarli, considera l'utilizzo di una WeakHashMap.

E BTW non è necessario eseguire l'override di equals e hashCode a meno che non si debbano considerare più istanze di un oggetto come uguali ...

1

Posso utilizzare un oggetto come chiave nella mappa, passarlo in giro, farlo sedere in un'altra raccolta e recuperare il suo partner dalla mappa in qualsiasi momento?

Sì, nessun problema qui.

Dopo che un oggetto è stato creato, tutto ciò che sto passando è un identificatore, giusto? Quindi probabilmente non c'è nessun problema lì. Cosa succede se serializzo e deserializza la chiave?

Proprio così, si sta solo passando un riferimento in giro - tutti punteranno allo stesso oggetto reale. Se serializzi o deserializzi l'oggetto, ciò creerebbe un nuovo oggetto. Tuttavia, se il tuo oggetto implementa correttamente e hashCode, dovresti comunque essere in grado di utilizzare il nuovo oggetto deserializzato per recuperare gli oggetti dalla mappa.

Eventuali altri avvertimenti? Dovrei usare qualcos'altro per mettere in correlazione le coppie di oggetti, come un numero che mi generi?

Come per gli avvertimenti, sì, non è possibile modificare nulla che causerebbe la modifica dell'hashCode dell'oggetto mentre l'oggetto si trova nella mappa.

3

Dipende dalla realizzazione della mappa che si sceglie:

  • HashMap utilizza equals() e hashCode(). Di default (in Object) questi sono basati sull'identità dell'oggetto, che funzionerà correttamente a meno che non si serializzi/deserializzi. Con una corretta implementazione di equals() e hashCode() in base al contenuto dell'oggetto non avrai problemi, a patto di non modificarlo mentre è una chiave in una mappa hash.

  • TreeMap utilizza compareTo(). Non esiste un'implementazione predefinita, quindi è necessario fornirne una. Le stesse limitazioni si applicano per l'implementazione di hashCode() e equals() sopra.

0

Si può prendere in considerazione lo BiMap di Google Collection.