Domanda

Ho ragione nel ritenere che se si dispone di un oggetto che è contenuto all'interno di un set Java <> (o come una chiave in una mappa <> è per questo), tutti i campi che vengono utilizzati per determinare l'identità o relazione (via hashCode(), equals(), compareTo() etc.) non può essere modificata senza causare un comportamento non specificato per le operazioni sulla raccolta? (Edit: come accennato nel quest'altra domanda )

(In altre parole, questi campi dovrebbero essere sia immutabile, o si dovrebbero richiedere l'oggetto da rimuovere dalla raccolta, poi cambiò, poi reinserito.)

Il motivo che mi chiedo è che stavo leggendo il Hibernate annotazioni guida di riferimento e ha un esempio in cui c'è un HashSet<Toy> ma la Toy classe ha campi name e serial che sono mutevoli e sono utilizzati anche nel <=> calcolo .. . una bandiera rossa se ne andò nella mia testa e io volevo solo per assicurarsi che ho capito le implicazioni di esso.

È stato utile?

Soluzione

Il Javadoc per Set dice

  

Nota: Grande attenzione deve essere esercitata se   oggetti mutabili sono utilizzati come set   elementi. Il comportamento di un insieme non è   specificato se il valore di un oggetto è   cambiato in modo che colpisce   uguale confronti mentre l'oggetto è   un elemento dell'insieme. Un caso particolare   di questo divieto è che non è   ammissibile per un set di contenere   stesso come elemento.

Questo significa semplicemente è possibile utilizzare oggetti mutabili in un set, e anche cambiarli. È solo necessario assicurarsi la modifica non influisce il modo in cui il HashSet trova le voci. Per hashCode(), che richiederebbe non cambiando i campi utilizzati per il calcolo <=>.

Altri suggerimenti

Questo è corretto, può causare alcuni problemi di localizzare la voce di mappa. Ufficialmente il comportamento è indefinito, quindi se si aggiunge a una hashset o come una chiave in una HashMap, non dovrebbe essere cambiarla.

Sì, che causerà che accadano cose brutte.

// Given that the Toy class has a mutable field called 'name' which is used
// in equals() and hashCode():
Set<Toy> toys = new HashSet<Toy>();
Toy toy = new Toy("Fire engine", ToyType.WHEELED_VEHICLE, Color.RED);
toys.add(toy);
System.out.println(toys.contains(toy)); // true
toy.setName("Fast truck");
System.out.println(toys.contains(toy)); // false

In un HashSet / HashMap, potrebbero mutare un oggetto contenuto per modificare i risultati di compareTo() funzionamento - Confronto relativa non viene utilizzato per individuare gli oggetti. Ma sarebbe fatale all'interno di un TreeSet / TreeMap.

Si può anche mutare gli oggetti che si trovano all'interno di un IdentityHashMap - altro che identità di un oggetto viene utilizzato per individuare i contenuti.

Anche se si possono fare queste cose con queste qualifiche, rendono il codice più fragile. Che cosa succede se qualcuno vuole passare a un TreeSet tardi, o aggiungere quel campo mutabile alla prova hashCode / uguaglianza?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top