Cómo eliminar varios elementos de Set / mapa y saber qué se retiraron queridos?

GhostCat saludos Monica C.:

Tengo un método que tiene para eliminar cualquier elemento que aparece en un (pequeño) Set<K> keysToRemovede algunos (potencialmente grande) Map<K,V> from. Pero removeAll()no lo hace, ya que necesito para volver todas las teclas que realmente fueron retirados, ya que el mapa puede o no contener claves que requieren la eliminación.

código de la escuela vieja es recta hacia adelante:

public Set<K> removeEntries(Map<K, V> from) {
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for (K keyToRemove : keysToRemove) {
        if (fromKeys.contains(keyToRemove)) {
            fromKeys.remove(keyToRemove);
            removedKeys.add(keyToRemove);
        }
    }
    return removedKeys;
}

Los mismos, escritas utilizando corrientes:

Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
        .filter(fromKeys::contains)
        .map(k -> {
            fromKeys.remove(k);
            return k;
        })
        .collect(Collectors.toSet());

Me parece que un poco más concisa, pero también me parece que lambda demasiado torpe.

Alguna sugerencia de cómo lograr el mismo resultado en menos maneras torpes?

Holger:

El “código de la vieja escuela” debería ser más bien

public Set<K> removeEntries(Map<K, ?> from) {
    Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
    removedKeys.retainAll(fromKeys);
    fromKeys.removeAll(removedKeys);
    return removedKeys;
}

Puesto que usted ha dicho que keysToRemovees bastante pequeño, la copia sobrecarga probable es que no importa. De lo contrario, utilice el bucle, pero no lo haga el hash de búsqueda dos veces:

public Set<K> removeEntries(Map<K, ?> from) {
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for(K keyToRemove : keysToRemove)
        if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
    return removedKeys;
}

Se puede expresar la misma lógica que una corriente tan

public Set<K> removeEntries(Map<K, ?> from) {
    return keysToRemove.stream()
        .filter(from.keySet()::remove)
        .collect(Collectors.toSet());
}

pero ya que este es un filtro de estado, que no es nada recomendable. Una variante limpiador sería

public Set<K> removeEntries(Map<K, ?> from) {
    Set<K> result = keysToRemove.stream()
        .filter(from.keySet()::contains)
        .collect(Collectors.toSet());
    from.keySet().removeAll(result);
    return result;
}

y si usted quiere maximizar el uso “streamy”, puede reemplazar from.keySet().removeAll(result);con from.keySet().removeIf(result::contains), que es bastante cara, ya que es la iteración sobre el mapa más grande, o con result.forEach(from.keySet()::remove), que no tiene esa desventaja, pero aún así, no es más legible a removeAll.

Con todo, el “código de la vieja escuela” es mucho mejor que eso.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=227292&siteId=1
Recomendado
Clasificación