java - modificar - como eliminar datos de una tabla en netbeans
Actualizar un objeto dentro de un conjunto (7)
Digamos que tengo este tipo en mi aplicación:
public class A {
public int id;
public B b;
public boolean equals(Object another) { return this.id == ((A)another).id; }
public int hashCode() { return 31 * id; //nice prime number }
}
y una estructura Set
. Ahora, tengo un objeto de tipo <A
>A
y quiero hacer lo siguiente:
- Si mi
A
está dentro del conjunto, actualice su campob
para que coincida con mi objeto. - De lo contrario, agrégalo al conjunto.
Por lo tanto, verificar si está allí es bastante fácil ( contains
), y agregarlo también es fácil. Mi pregunta es esta: ¿cómo obtengo un control para actualizar el objeto dentro? Interface Set
no tiene un método get
, y lo mejor que pude pensar fue eliminar el objeto en el conjunto y agregar el mío. otra, incluso peor, alternativa es atravesar el conjunto con un iterador para intentar localizar el objeto.
Con mucho gusto recibiré mejores sugerencias ... Esto incluye el uso eficiente de otras estructuras de datos.
Yuval = 8-)
EDITAR : Gracias a todos por responder ... Desafortunadamente no puedo "aceptar" las mejores respuestas aquí, las que sugieren usar un Map
, porque cambiar el tipo de la colección radicalmente para este propósito sería un poco extremo (esta colección ya está mapeado a través de Hibernate ...)
¿Qué pasa con Map <A,A
> Sé que es redundante, pero creo que obtendrá el comportamiento que desea? Realmente me encantaría ver a Set tener un método get (Object o) en él.
Como un conjunto solo puede contener una instancia de un objeto (como se define por sus métodos equals y hashCode), simplemente elimínelo y luego agréguelo. Si ya había uno, ese otro será eliminado del Conjunto y reemplazado por el que desee.
Tengo un código que hace algo similar: estoy almacenando objetos en el caché para que, en cualquier lugar donde aparezca un objeto en particular en un montón de lugares diferentes en la interfaz gráfica de usuario, siempre sea el mismo. En ese caso, en lugar de usar un Conjunto, estoy usando un Mapa, y luego recibo una actualización, la recupero del Mapa y la actualizo en lugar de crear una nueva instancia.
Es posible que desee generar un decorador llamado ASet y utilizar un mapa interno como la estructura de datos de respaldo
class ASet {
private Map<Integer, A> map;
public ASet() {
map = new HashMap<Integer, A>();
}
public A updateOrAdd(Integer id, int delta) {
A a = map.get(a);
if(a == null) {
a = new A(id);
map.put(id,a);
}
a.setX(a.getX() + delta);
}
}
También puedes echar un vistazo a la API de Trove. Si bien eso es mejor para el rendimiento y para la contabilidad de que está trabajando con variables primitivas, expone muy bien esta característica (por ejemplo, map.adjustOrPutValue (key, initialValue, deltaValue).
Está un poco fuera del alcance, pero olvidó volver a implementar hashCode (). Cuando anula los iguales, anule hashCode (), incluso en un ejemplo.
Por ejemplo; contains () probablemente saldrá mal cuando tengas una implementación HashSet de Set, ya que HashSet usa el hashCode of Object para localizar el bucket (un número que no tiene nada que ver con la lógica de negocios), y solo iguala () los elementos dentro de ese cangilón.
public class A {
public int id;
public B b;
public int hashCode() {return id;} // simple and efficient enough for small Sets
public boolean equals(Object another) {
if (object == null || ! (object instanceOf A) ) {
return false;
}
return this.id == ((A)another).id;
}
}
public class Logic {
/**
* Replace the element in data with the same id as element, or add element
* to data when the id of element is not yet used by any A in data.
*/
public void update(Set<A> data, A element) {
data.remove(element); // Safe even if the element is not in the Set
data.add(element);
}
}
EDITAR Yuvalindicó correctamente que Set.add no sobrescribe un elemento existente, sino que solo agrega si el elemento aún no está en la colección (con "es" implementado por iguales)
Nadie ha mencionado esto todavía, pero basar hashcode o igual en una propiedad mutable es una de esas realmente grandes cosas que no deberías hacer. No te obsesiones con la identidad del objeto después de que abandones el constructor, ya que al hacerlo aumenta tus posibilidades de tener errores realmente difíciles de descifrar. Incluso si no te golpean con errores, el trabajo de contabilidad para asegurarte de que siempre actualizas correctamente todas y cada una de las estructuras de datos que dependen de equal y que hashcode sea consistente superarán con creces los beneficios percibidos de poder simplemente cambiar la identificación de el objeto mientras corres
En su lugar, le recomiendo encarecidamente que ingrese el ID a través del constructor y, si necesita cambiarlo, cree una nueva instancia de A. Esto forzará a los usuarios de su objeto (incluido usted) a interactuar correctamente con las clases de recopilación (y muchos otros) que confían en el comportamiento inmutable en iguales y hashcode.
No creo que pueda hacer que sea más fácil que usar remove / add si está usando un Set.
set.remove(a);
set.add(a);
Si se encuentra una A coincidente, se eliminará y luego se agregará la nueva, ni siquiera se necesita el condicional if (set.contains(A))
.
Si tiene un objeto con una ID y un campo actualizado y realmente no le importan otros aspectos de ese objeto, simplemente deséchelo y reemplácelo.
Si necesita hacer algo más con la A que coincida con esa ID, deberá iterar a través del Conjunto para encontrarla o usar un Contenedor diferente (como el Mapa como Jason sugirió).
Realmente desea usar un Map<int,A>
, no un Set<A>
.
Luego asigne la ID (aunque también esté almacenada en A
!) Al objeto. Entonces, almacenar algo nuevo es esto:
A a = ...;
Map<Integer,A> map = new HashMap<Integer,A>();
map.put( a.id, a );
Su algoritmo de actualización completo es:
public static void update( Map<Integer,A> map, A obj ) {
A existing = map.get( obj.id );
if ( existing == null )
map.put( obj.id, obj );
else
existing.b = obj.b;
}
Sin embargo, podría ser aún más simple. Supongo que tienes más campos que en A
que lo que diste. Si este no es el caso , simplemente usar un Map<Integer,B>
es, de hecho, lo que quiere, y luego se colapsa a nada:
Map<Integer,B> map = new HashMap<Integer,B>();
// The insert-or-update is just this:
map.put( id, b );