2010-04-14 12 views
16

Actualmente tengo que escribir lo siguiente para actualizar un elemento que ya figuran en un set:¿por qué no se reemplazó el método() definido en la interfaz Establecer?

Set mySet= ... 
Element e1 = new Element (...); 
.... 
.... 
Element e2 = new Element (...); 
\\e1 and e2 are different instances, but equals. 

\\update the element contained into the Set 
if (mySet.contains(e2)){ 
    mySet.remove(e2); 
    myset.add(e2); 
} 

eso no se ven bien. ¿Hay una alternativa?

+2

¿El tipo de 'elemento 'es tal que dos instancias del tipo son" iguales "en lo que respecta al método igual() pero no son" iguales "de alguna otra manera que sea importante para el programa? –

+1

el elemento en la instrucción add es diferente de las instrucciones contains y remove? –

+0

@Martijn Courteaux: incluso si se usa la misma instancia en esas tres llamadas a funciones, podría haber una instancia diferente que se almacena en el conjunto y es "igual a" 'elemento'. Parece que el OP quiere reemplazar la instancia actualmente en el conjunto con una instancia diferente, "igual". Diría que la razón por la que no existe un método para hacer lo que se desea es porque ese no es el uso típico, o posiblemente sugerido, de Set. –

Respuesta

16

Un conjunto es una estructura de datos creada para evitar la duplicación medio de usar equals() en el objeto; eso también significa que dos objetos que son iguales() entre sí se consideran perfectamente equivalentes. Es decir, si usa la versión que ya está en el Conjunto o la nueva, su código debería funcionar de la misma manera.

Si desea actualizar el objeto con un nuevo valor, este no es el caso (las dos versiones no pueden reemplazarse), y luego debe usar otra estructura de datos (por ejemplo, un Mapa, donde puede anular fácilmente el valor, en este caso, la clave puede ser incluso el objeto mismo).

+2

sí. Ahora me doy cuenta de que mi definición de iguales() era demasiado imprecisa, lo que hace que algunos objetos sean más iguales que otros;) – Eleco

2

Creo que la alternativa es usar add.

Desde el docs:

añade el elemento especificado a este conjunto si no está ya presente (opcional operación ). Más formalmente, agrega el elemento especificado e a este conjunto si el conjunto no contiene ningún elemento e2 tal que (e == null? E2 == null: e.equals (e2)). Si este conjunto ya contiene el elemento , la llamada deja el conjunto sin cambios y devuelve falso.

Sin embargo, en realidad no puedo decir de su pregunta si usted está tratando de actualización o sustitución un elemento. Cuando cambia la propiedad de un elemento, esos cambios se reflejan automáticamente en el Set porque el conjunto contiene referencias, por lo que no es necesario actualizar . Si intenta reemplazar un elemento diferente, un método replace sería redundante como se explica en Stephen C.

(después de la pregunta de edición)

E1 y E2 son diferentes instancias, pero iguales.

Sugiero que implemente la igualdad en Element. De esta manera, el método add comprueba la existencia de un elemento no por referencia (el valor predeterminado Object.equals), sino por su concepto de igualdad en Element. Entonces, incluso si las referencias de e1 y e2 son diferentes, e1.equals(e2) == true.

+3

esto no actualiza el antiguo objeto equivalente con el nuevo objeto – Progman

+0

Recuerde que su objeto debe sobrescribirse equals y hashCode para que el conjunto pueda identificar si realmente son el mismo objeto. –

+0

@Shervin: Eso está mal. La documentación de Set API establece claramente que las verificaciones de igualdad se basan en el método equals. Las implementaciones de conjuntos específicos (por ejemplo, HashSet) pueden tener un requisito adicional que hashCode debe coincidir también, pero ese no es un requisito general para el uso del conjunto. – jarnbjo

1

por definición, un conjunto no puede contener un elemento más de una vez, por lo que su elemento contiene-> eliminar-> agregar no tiene sentido. solo agregue su artículo tantas veces como desee al conjunto.

1

No es necesario quitar y luego agregar. Solo modifica el objeto directamente. Como Sets (o cualquier colección) simplemente almacena la referencia, no necesita un método de reemplazo().

EDITAR: la instrucción anterior es INCORRECTA. Ver http://java.sun.com/j2se/1.4.2/docs/api/java/util/Map.html

Nota: el gran cuidado debe tener cuidado si se utilizan objetos mutables como teclas de mapas. El comportamiento de un mapa no se especifica si el valor de un objeto se cambia de una manera que afecta igual a comparaciones mientras que el objeto es una clave en el mapa

+2

La modificación de un objeto que está en un 'Conjunto' (especialmente un' HashSet') es una operación peligrosa. Y si la modificación cambia los resultados de los métodos 'equals()' y 'hashCode()' de ese objeto, entonces es simplemente incorrecto y está pidiendo todo tipo de errores. –

+0

@Joachim - Punto tomado. Aquí está la línea oficial de javadocs: "Nota: se debe tener mucho cuidado si los objetos mutables se utilizan como claves de mapa. El comportamiento de un mapa no se especifica si el valor de un objeto se cambia de manera que afecte a las comparaciones mientras el objeto es una clave en el mapa " –

+0

Actualizó la publicación. Gracias Joachim! –

5

¿Por qué no se reemplace () método definido en la interfaz Establecer?

me ocurren tres razones:

  1. Es funcionalmente redundante: set.replace(old, nu) es simplemente if (set.remove(old)) { set.add(nu) } por ejemplo.

  2. El comportamiento en el caso en que old no está presente agrega complicaciones.

  3. Añadiendo replace al Set API obliga a todas las implementaciones de Set a implementar un método (redundante).

Puede ser que haya razones más profundas; p.ej. para hacer con la implementabilidad de replace en algún caso oscuro.

Sin embargo, como otros han señalado su caso de uso no requiere un replace en absoluto. El código tiene el mismo efecto (*) como esto:

Set myset = ... 
    myset.add(element); 

(* En realidad, usted podría ser capaz de detectar una diferencia si su método element.equals(Object) compara elemento objetos campo por campo Dependiendo de la implementación Conjunto, es posible. obtener diferentes referencias de objeto en los conjuntos después de ejecutar las dos secuencias de código. Pero, ¡IMO estaría pidiendo problemas si hiciera suposiciones sobre ese tipo de cosas!)

+1

Esto no sería redundante. Por ejemplo, se puede agregar cierta optimización, especialmente (pero no por fin) con conjuntos ordenados. Este método no se perdió debido a la redundancia, sino porque la "necesidad de reemplazar" es muy poco frecuente. –

+0

Es * funcionalmente * redundante. –

Cuestiones relacionadas