Pregunta

Este error me llevó un tiempo encontrar ...

Tenga en cuenta que este método:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    set.remove(obj)
}

invoco el método con un conjunto de hash no vacío, pero ningún elemento se eliminará!

¿Por qué sería?

¿Fue útil?

Solución

Para un HashSet, esto puede ocurrir si los cambios hashCode del objeto después de que se ha añadido al conjunto. El método HashSet.remove () puede entonces buscar en el cubo Hash mal y que encontrarlo.

Esto probablemente no pasaría si lo hiciera Iterator.remove (), pero en cualquier caso, el almacenamiento de objetos en un HashSet cuyo código hash puede cambiar es un accidente a punto de ocurrir (como usted ha descubierto).

Otros consejos

Puzzle? Si Object.hashCode, Object.equals o el "conjunto de hash" se llevaron a cabo de forma incorrecta (véase, por ejemplo, java.net.URL - uso URI).

Además, si el conjunto (directa o indirectamente) contiene en sí, es probable que suceda (exactamente lo que es la implementación y la fase de la luna dependiente) algo extraño.

¿Cuál es el tipo de implementación del conjunto y qué objetos están dentro del conjunto?

  • Si se trata de un HashSet, asegúrese de que el valor de código hash del objeto () método se mantiene constante entre set.put(...) y set.remove(...).
  • Si es un TreeSet, asegúrese de que no se hicieron modificaciones al objeto que afecta comparador del conjunto o método compareTo del objeto.

En ambos casos, el código entre set.put(...) y set.remove(...) viola el contrato definido por la implementación de la clase respectiva. Como regla general, es una buena idea usar objetos inmutables como contenido conjunto (y como llaves mapa). Por su propia naturaleza, este tipo de objetos no se pueden cambiar mientras se almacenan dentro de un conjunto.

Si está utilizando alguna otra aplicación conjunto, echa un vistazo a su Javadoc de su contrato; pero por lo general ya sea equals o hashCode deben seguir siendo la misma mientras que el objeto está contenido en el conjunto.

Más allá de los desaparecidos ';' después set.remove(obj), puede suceder en tres situaciones (citado de javadoc).

ClassCastException - if the type of the specified element is incompatible with this set (optional).
NullPointerException - if the specified element is null and this set does not support null elements (optional). 
UnsupportedOperationException - if the remove method is not supported by this set.

También puede probar:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    iterator.remove();
}

¿Debería ser:

public void foo(Set<Object> set)
{
    Iterator i = set.iterator();
    i.next();
    i.remove();
}

El error podría ser algo que ver con:

  

public void remove ()

     

El comportamiento de un iterador es   sin especificar si el subyacente   colección se modifica mientras la   iteración en curso en modo alguno   que no sea llamando a este método.

( Referencia)

No puedo evitar sentir que (parte de) el problema es que el conjunto se pasa por valor, no referencia. No tengo mucha experiencia en Java, sin embargo, por lo que podría estar totalmente equivocado.

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