una predicados nodo lista eliminar dinamicos como java collections filtering guava predicate

predicados - como eliminar un nodo de una lista en java



Guava-¿Cómo eliminar de una lista, en función de un predicado, el seguimiento de lo que se eliminó? (5)

Capturaría los elementos eliminados en tu código Predicado.

List<String> removedElements = Lists.newArrayList(); final Iterables.removeIf(list, new Predicate<String>() { @Override public boolean apply(String input) { if ("a".equals(input)) { removedElements.add(input); return true; } return false; } });

Tengo un ArrayList para filtrar y varios Predicate Guava para filtrarlo. Esta lista tendrá solo 50-100 elementos.

Estaba planeando Iterables.removeIf usando cada predicado por turno. Tal vez no sea lo más eficiente posible, pero no importa (al menos removeIf tiene alguna optimización para las listas RandomAccess)

Para la depuración, quiero registrar concisamente lo que hizo cada predicado. p.ej

Pred0 removed [a, c, g] Pred1 removed [] Pred2 removed [b, f]

Hay algunas soluciones obvias de corte, pero ¿qué sugieres que sean las más limpias?

Para puntos de bonificación, también debería ser razonablemente eficiente. ;)


Esta puede ser una ocasión cuando el uso de un bucle es más simple.

List<MyType> list = Predicate<MyType>[] predicates = Map<Predicate, List<MyType>> removed = new LinkedHashMap<Predicate, List<MyType>>(); for(Iterator<MyType> iter=list.iterator();list.hasNext();) { MyType mt = iter.next(); for(Predicate<MyType> pred: predicates) if(pred.apply(mt)) { List<MyType> mts = removed.get(pred); if(mts == null) removed.put(pred, mts = new ArrayList<MyType>()); mts.add(mt); iter.remove(); break; } }


Estoy de acuerdo con el autor de Peter.

Pero si quieres divertirte, también puedes ajustar cada uno de tus predicados dentro de un predicado que delegaría en el predicado envuelto, y almacenar los valores para los cuales se devuelve verdadero dentro de un Map<Predicate, List<Foo>> removedByPredicate :

class PredicateWrapper implements Predicate<Foo> { private Predicate<Foo> delegate; public PredicateWrapper(Predicate<Foo> delegate) { this.delegate = delegate; } @Override public boolean apply(Foo foo) { boolean result = delegate.apply(foo); if (result) { List<Foo> objectsRemoved = removedByPredicate.get(delegate); if (objectsRemoved == null) { objectsRemoved = Lists.newArrayList(); removedByPredicate.put(delegate, objectsRemoved); } objectsRemoved.add(foo); } return result; } }


Investigaría en predicados observables . La idea: cada vez que un método de apply predicados está por volver verdadero, se lanzará una notificación a los oyentes:

Iterable<?> iterable = getIterable(); Collection<ObservablePredicate> predicates = getPredicates(); PredicatesLogger log = new PredicatesLogger(predicates); // listens to all predicates for (ObservablePredicate pred : predicates) { Iterables.removeIf(iterable, pred); log.print(); log.reset(); }

El ObservableLogger es un decorador para Predicate :

public class ObservableLogger implements Predicate { private Predicate predicate; private List<Listener> listeners = new ArrayList<Listener>(); // usual stuff for observer pattern @Override public boolean apply(Object input) { boolean result = predicate.apply(input); fire(result); return result; } // a fire method }

PredicateLogger necesita un constructor que se agregue como oyente a los predicados. Recibirá las notificaciones y el caché de los predicados que dispararon los eventos (la clase Event necesita un campo apropiado para esa información). print creará el mensaje de registro, reset borrará la memoria caché de registradores (para la próxima ejecución).


Supongo que necesitas:

Predicate<XXX> predicate1 = new Predicate<XXX>(){ @Override public boolean apply(XXX input) { if(...) //satisfy your filter return true; else return false; }}; Predicate<XXX> predicate2 = new Predicate<XXX>(){ @Override public boolean apply(XXX input) { if(...) //satisfy your filter return true; else return false; }}; Predicate allPredicates = Predicates.and(predicate1, predicate2); //or Predicates.or(predicate1, predicate2); Collection<XXX> list2 = Collections2.filter(list, allPredicates);