Pregunta

Estoy en lo cierto al suponer que si tienes un objeto que se encuentra dentro de un Conjunto de Java<> (o como una clave en un Mapa<> para el caso), los campos que se utilizan para determinar la identidad o relación (a través de hashCode(), equals(), compareTo() etc.) no se puede cambiar sin causar sin especificar el comportamiento de las operaciones en la colección?(edición:como se menciona en el esta otra pregunta)

(En otras palabras, estos campos deben ser inmutables, o usted necesita el objeto para ser eliminado de la colección, a continuación, cambiar, a continuación, vuelva a insertar.)

La razón que pido es que me estaba leyendo el Hibernate annotations guía de referencia y él tiene un ejemplo donde hay un HashSet<Toy> pero el Toy la clase tiene campos name y serial que son mutables y también son utilizados en la hashCode() cálculo de...una bandera roja se apagó en mi cabeza y yo sólo quería asegurarme de que he entendido las implicaciones de la misma.

¿Fue útil?

Solución

El Javadoc para Set dice

  

Nota: El gran cuidado debe ejercerse si   objetos mutables se utilizan como conjunto   elementos. El comportamiento de un conjunto no es   especificado si el valor de un objeto es   cambiado de una manera que afecta   es igual a comparaciones mientras que el objeto es   un elemento en el conjunto. Un caso especial   de esta prohibición es que no es   permisible para un conjunto de contener   a sí mismo como un elemento.

Esto simplemente significa que puede utilizar objetos mutables en un conjunto, e incluso cambiarlos. Usted sólo debe asegurarse de que el cambio no afecta a la forma en que el HashSet encuentra los artículos. Para hashCode(), que requeriría no cambiar los campos que se utilizan para el cálculo de <=>.

Otros consejos

Eso es correcto, puede causar algunos problemas para localizar la entrada del mapa. Oficialmente, el comportamiento no está definido, por lo que si se agrega a una hashset o como una llave en una HashMap, no debe ser el cambio de la misma.

Sí, eso hará que sucedan cosas malas.

// 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

En un HashSet / HashMap, que podría mutar un objeto contenido para cambiar los resultados de la operación compareTo() - comparación relativa no se utiliza para localizar objetos. Pero sería fatal dentro de un TreeSet / TreeMap.

También puede mutar objetos que se encuentran dentro de un IdentityHashMap - nada que no sea la identidad del objeto se utiliza para localizar contenidos.

A pesar de que usted puede hacer estas cosas con estos requisitos, hacen que el código sea más frágil. ¿Y si alguien quiere cambiar a un TreeSet más tarde, o añadir ese campo mutable a la prueba hashCode / igualdad?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top