java - descargar - iterando sobre y eliminando de un mapa
java offline (12)
¿Hay una solución mejor?
Bueno, definitivamente hay una mejor manera de hacerlo en una sola declaración , pero eso depende de la condición basada en qué elementos se eliminan.
Por ejemplo: elimine todos aquellos elementos donde el value
es la prueba , luego use a continuación:
map.values().removeAll(Collections.singleton("test"));
ACTUALIZACIÓN Se puede hacer en una sola línea usando la expresión Lambda en Java 8.
map.entrySet().removeIf(e-> <boolean expression> );
Sé que esta pregunta es demasiado antigua, pero no hay ningún problema en actualizar la mejor manera de hacer las cosas :)
Esta pregunta ya tiene una respuesta aquí:
Estaba haciendo:
for (Object key : map.keySet())
if (something)
map.remove(key);
que lanzó una excepción de modificación concurrente, por lo que la cambié a:
for (Object key : new ArrayList<Object>(map.keySet()))
if (something)
map.remove(key);
Esto y cualquier otro procedimiento que modifique el mapa están en bloques sincronizados.
¿Hay una solución mejor?
si a nadie se le ocurre una solución mejor, primero diga que no recibe el tick;)
A partir de Java 1.8, puedes hacer esto utilizando expresiones y secuencias lambda:
map.entrySet().removeIf(e-> <boolean expression> );
Aquí hay un ejemplo de código para usar el iterador en un bucle for para eliminar la entrada.
Map<String, String> map = new HashMap<String, String>() {
{
put("test", "test123");
put("test2", "test456");
}
};
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
if(entry.getKey().equals("test")) {
it.remove();
}
}
Estoy de acuerdo con Paul Tomblin. Usualmente uso el iterador del conjunto de teclas y luego baso mi condición en el valor de esa clave:
Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
Integer key = it.next();
Object val = map.get(key);
if (val.shouldBeRemoved()) {
it.remove();
}
}
Java 8 admite un enfoque más declarativo de la iteración, ya que especificamos el resultado que queremos en lugar de cómo calcularlo. Los beneficios del nuevo enfoque son que puede ser más legible, menos propenso a errores.
public static void mapRemove() {
Map<Integer, String> map = new HashMap<Integer, String>() {
{
put(1, "one");
put(2, "two");
put(3, "three");
}
};
map.forEach( (key, value) -> {
System.out.println( "Key: " + key + "/t" + " Value: " + value );
});
map.keySet().removeIf(e->(e>2)); // <-- remove here
System.out.println("After removing element");
map.forEach( (key, value) -> {
System.out.println( "Key: " + key + "/t" + " Value: " + value );
});
}
Y el resultado es el siguiente:
Key: 1 Value: one
Key: 2 Value: two
Key: 3 Value: three
After removing element
Key: 1 Value: one
Key: 2 Value: two
Tal vez pueda recorrer el mapa buscando las claves para eliminarlas y almacenarlas en una colección separada. A continuación, elimine la colección de claves del mapa. La modificación del mapa durante la iteración suele estar mal vista. Esta idea puede ser sospechosa si el mapa es muy grande.
Tienes que usar el Iterator
para eliminar de forma segura el elemento mientras recorres un mapa.
Una forma alternativa, más verbosa.
List<SomeObject> toRemove = new ArrayList<SomeObject>();
for (SomeObject key: map.keySet()) {
if (something) {
toRemove.add(key);
}
}
for (SomeObject key: toRemove) {
map.remove(key);
}
Utilice un iterador real.
Iterator<Object> it = map.keySet().iterator();
while (it.hasNext())
{
it.next();
if (something)
it.remove();
}
En realidad, es posible que deba iterar sobre entrySet()
lugar de keySet()
para que funcione.
Y esto debería funcionar también ...
ConcurrentMap<Integer, String> running = ... create and populate map
Set<Entry<Integer, String>> set = running.entrySet();
for (Entry<Integer, String> entry : set)
{
if (entry.getKey()>600000)
{
set.remove(entry);
}
}
HashMap concurrente
Puedes usar java.util.concurrent.ConcurrentHashMap
.
Implementa ConcurrentMap
(que amplía la interfaz del Map
).
Ej . :
Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();
for (Object key : map.keySet()) {
if (something) {
map.remove(key);
}
}
Este enfoque deja su código intacto. Sólo el tipo de map
difiere.
Set s=map.entrySet();
Iterator iter = s.iterator();
while (iter.hasNext()) {
Map.Entry entry =(Map.Entry)iter.next();
if("value you need to remove".equals(entry.getKey())) {
map.remove();
}
}