我要过滤ArrayList
,并使用各种Guava Predicate
进行过滤。该列表只有50-100个元素。
我计划依次使用每个谓词Iterables.removeIf
。它可能不是最有效的,但没关系(至少removeIf
对RandomAccess列表有一些优化)
对于调试,我想简明地记录每个谓词的作用。 e.g。
Pred0 removed [a, c, g]
Pred1 removed []
Pred2 removed [b, f]
有一些明显的黑客解决方案,但你认为最干净的是什么?
对于奖励积分,它也应该合理有效。 ;)
答案 0 :(得分:32)
我会在您的谓词代码中捕获已删除的元素。
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;
}
});
答案 1 :(得分:5)
这可能是使用循环最简单的场合。
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;
}
}
答案 2 :(得分:4)
我会调查 observable谓词。这个想法:每次,谓词apply
方法即将返回true,它会向听众发出通知:
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();
}
ObservableLogger
是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
需要一个构造函数将自身添加为谓词的侦听器。它将接收通知并缓存触发事件的谓词(Event
类需要该信息的适当字段)。 print
将创建日志消息,reset
将清除记录器缓存(用于下次运行)。
答案 3 :(得分:1)
我同意彼得的回复。
但是如果你想获得乐趣,你也可以将每个谓词包装在一个谓词中,该谓词将委托给包装的谓词,并存储在Map<Predicate, List<Foo>> removedByPredicate
内返回true的值:
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;
}
}
答案 4 :(得分:-4)
我想你需要:
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);