Cómo mantener dos iteradores sobre el mapa en java y eliminar claves intermedias sin ConcurrentModificationException
iterator hashmap (3)
No puede usar iterator.remove () en keySet del mapa ya que es solo una "vista" en la estructura interna del mapa.
Pero puede usar un iterador en entrySet () del mapa, donde cada elemento es una instancia de Map.Entry que contiene todas las entradas de mapas (pares clave / valor). Puede invocar iterator.remove () en este iterador, que eliminará eficazmente el par clave / valor correspondiente del mapa.
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(Integer.valueOf(0), "0");
map.put(Integer.valueOf(1), "1");
map.put(Integer.valueOf(2), "2");
map.put(Integer.valueOf(3), "3");
map.put(Integer.valueOf(4), "4");
System.out.println(map);
Iterator<Map.Entry<Integer, String>> entryIter = map.entrySet().iterator();
while (entryIter.hasNext()) {
Map.Entry<Integer, String> entry = entryIter.next();
if (entry.getKey().intValue() % 2 == 0)
entryIter.remove();
}
System.out.println(map);
Espero que ayude
Saludos
Tengo que procesar un Map <BitSet,List<List<Integer>> MyMap
if (key1 contains all of corresponding true bits of key2)
Remove from key2 all those values which are common with key1)
En este proceso, si la cantidad de elementos en una lista cae por debajo de un UMBRAL (entero positivo definido por el usuario), se elimina. Además, si el mapa contiene una lista vacía, se eliminará la clave correspondiente.
Estoy usando el siguiente código:
List<BitSet> keys = new ArrayList<>(MyMap.keySet());
ListIterator it1=keys.listIterator();
while(it1.hasNext()) {
BitSet key1=(BitSet)it1.next();
ListIterator it2=keys.listIterator(it1.nextIndex());
while(it2.hasNext()) {
BitSet key2=(BitSet)it2.next();
BitSet ankey=(BitSet)key1.clone();
ankey.and(key2);
if(ankey.equals(key1)) {//key1 is subset and key2 is superset
if(removePoints(key1,key2)) {
it1.remove();
break;
}
}
else if(ankey.equals(key2)) {
if(removePoints(key2,key1)) {
it2.remove();
}
}
}
}
public static boolean removePoints(BitSet key1,BitSet key2)
{
List<List<Integer>> list1=MyMap.get(key1);
List<List<Integer>> list2=MyMap.get(key2);
Boolean ret=false;
for(int i=0;i<list1.size();i++) {
List<Integer> sublist1=list1.get(i);
for(int j=0;j<list2.size();j++) {
List<Integer> sublist2=list2.get(j);
sublist1.removeAll(sublist2);
if(sublist1.isEmpty())
break;
}
if(sublist1.size()<=THRESHOLD)
list1.remove(sublist1);
if( list1.isEmpty()) {
MyMap.remove(key1);
ret=true;
}
}
return ret;
}
Pero el programa está dando error:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification
at java.util.ArrayList$Itr.next
Además, no estoy seguro de si esta es la manera eficiente de codificar? Como el mapa contiene ~ 2000 entradas. Por favor avise.
Una Iterator
ConcurrentModificationException
puede ocurrir cuando la colección subyacente se modifica después de que se crea un Iterator
, y esa modificación no se realiza a través del mismo Iterator
.
En su código tal como está escrito, solo hay un lugar donde eso puede suceder: la it1
entre it1
e it2
, que son iteradores en la misma colección. Cada vez que llame a remove
en uno, el otro se interrumpirá la próxima vez que llame a next
.
Hay una variedad de formas de evitar esto, pero una forma es separar lo que está eliminando de su colección ''clave'' de la iteración de esa colección, así:
List<BitSet> allKeys = new ArrayList<>(MyMap.keySet());
List<BitSet> removedKeys = new ArrayList<>();
for (ListIterator<BitSet> it1 = allKeys.listIterator(); it1.hasNext(); ) {
BitSet key1 = it1.next();
for (ListIterator<BitSet> it2 = allKeys.listIterator(it1.nextIndex()); it2.hasNext(); ) {
BitSet key2 = it2.next();
BitSet ankey=(BitSet)key1.clone();
ankey.and(key2);
if(ankey.equals(key1)) {//key1 is subset and key2 is superset
if(removePoints(key1,key2)) {
removedKeys.add(key1);
break;
}
}
else if(ankey.equals(key2)) {
if(removePoints(key2,key1)) {
removedKeys.add(key2);
break;
}
}
}
}
allKeys.removeAll(removedKeys);
allKeys
estará entonces en el estado que espera. Supongo que algún tiempo después querrá llamar a MyMap.keySet().retainAll()
o similar.
Dejé de intentar leer su código después de ver nombres de variables como ll1, ll2, list1, list2, it1, it2.
. sin embargo, puedes mirar este enlace para encontrar una solución a un problema similar.