recorrer lista funciona como java set

lista - recorrer un set java



¿Cómo iterar y modificar los conjuntos de Java? (5)

Digamos que tengo un conjunto de enteros, y quiero incrementar cada entero en el conjunto. ¿Cómo haría esto?

¿Puedo añadir y eliminar elementos del conjunto mientras lo itero?

¿Tendría que crear un nuevo conjunto en el que "copiaría y modificaría" los elementos, mientras estoy iterando el conjunto original?

EDITAR: ¿Qué pasa si los elementos del conjunto son inmutables?



No me gusta mucho la semántica del iterador, por favor considere esto como una opción. También es más seguro a medida que publicas menos de tu estado interno

private Map<String, String> JSONtoMAP(String jsonString) { JSONObject json = new JSONObject(jsonString); Map<String, String> outMap = new HashMap<String, String>(); for (String curKey : (Set<String>) json.keySet()) { outMap.put(curKey, json.getString(curKey)); } return outMap; }


Puede crear un contenedor mutable de la primitiva int y crear un conjunto de esos:

class MutableInteger { private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } } class Test { public static void main(String[] args) { Set<MutableInteger> mySet = new HashSet<MutableInteger>(); // populate the set // .... for (MutableInteger integer: mySet) { integer.setValue(integer.getValue() + 1); } } }

Por supuesto, si está utilizando un HashSet, debe implementar el método hash, equals en su MutableInteger, pero eso está fuera del alcance de esta respuesta.


Puede eliminar de forma segura de un conjunto durante la iteración con un objeto iterador; intentar modificar un conjunto a través de su API mientras se itera romperá el iterador. la clase Set proporciona un iterador a través de getIterator ().

sin embargo, los objetos enteros son inmutables; Mi estrategia sería iterar a través del conjunto y para cada Entero i, agregar i + 1 a un nuevo conjunto temporal. Cuando termine de iterar, elimine todos los elementos del conjunto original y agregue todos los elementos del nuevo conjunto temporal.

Set<Integer> s; //contains your Integers ... Set<Integer> temp = new Set<Integer>(); for(Integer i : s) temp.add(i+1); s.clear(); s.addAll(temp);


Puede hacer lo que quiera si usa un objeto iterador para revisar los elementos en su conjunto. Puedes eliminarlos sobre la marcha y está bien. Sin embargo, eliminarlos mientras está en un bucle for (ya sea "estándar", de cada tipo) te meterá en problemas:

Set<Integer> set = new TreeSet<Integer>(); set.add(1); set.add(2); set.add(3); //good way: Iterator<Integer> iterator = set.iterator(); while(iterator.hasNext()) { Integer setElement = iterator.next(); if(setElement==2) { iterator.remove(); } } //bad way: for(Integer setElement:set) { if(setElement==2) { //might work or might throw exception, Java calls it indefined behaviour: set.remove(setElement); } }

Según el comentario de @ mrgloom, aquí hay más detalles sobre por qué la "mala" forma descrita arriba es, bueno ... mala:

Sin entrar en demasiados detalles sobre cómo implementa Java esto, a un alto nivel, podemos decir que la "mala" forma es mala porque está claramente estipulada como tal en los documentos de Java:

https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html

estipular, entre otros, eso (énfasis mío):

" Por ejemplo, generalmente no se permite que un hilo modifique una Colección mientras otro hilo se itera sobre él. En general, los resultados de la iteración no están definidos en estas circunstancias. Algunas implementaciones de Iterator (incluidas las de toda la colección de propósito general). implementaciones proporcionadas por el JRE) pueden optar por lanzar esta excepción si se detecta este comportamiento "(...)

" Tenga en cuenta que esta excepción no siempre indica que un objeto ha sido modificado simultáneamente por un hilo diferente. Si un único hilo emite una secuencia de invocaciones de métodos que viola el contrato de un objeto, el objeto puede lanzar esta excepción. Por ejemplo, si un hilo modifica una colección directamente mientras se itera sobre la colección con un iterador de fail-fast, el iterador arrojará esta excepción ".

Para profundizar en los detalles: un objeto que se puede usar en un bucle forEach necesita implementar la interfaz "java.lang.Iterable" (javadoc here ). Esto produce un Iterator (a través del método "iterador" que se encuentra en esta interfaz), que se crea una instancia bajo demanda y contendrá internamente una referencia al objeto Iterable desde el que se creó. Sin embargo, cuando se utiliza un objeto Iterable en un ciclo forEach, la instancia de este iterador se oculta al usuario (no puede acceder a él usted mismo de ninguna manera).

Esto, junto con el hecho de que un iterador es bastante estable, es decir, para hacer su magia y tener respuestas coherentes para sus métodos "siguiente" y "tiene ahora", necesita que el objeto de respaldo no sea modificado por otra cosa que no sea el iterador mismo mientras itera, lo hace de forma que arroje una excepción tan pronto como detecte que algo cambió en el objeto de respaldo mientras se itera sobre él.

Java llama a esta iteración "a prueba de fallos": es decir, hay algunas acciones, generalmente aquellas que modifican una instancia Iterable (mientras que un iterador está iterando sobre ella). La parte de "falla" de la noción de "falla rápida" se refiere a la capacidad de un iterador para detectar cuándo ocurren tales acciones de "falla". La parte "rápida" del "fail-fast" (y que, en mi opinión, debería denominarse "best-effort-fast"), terminará la iteración mediante ConcurrentModificationException tan pronto como pueda detectar que una acción "fail" ha ocurrir.