Java Guava - 如何根据谓词从列表中删除,跟踪已删除的内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6494614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Guava - How to remove from a list, based on a predicate, keeping track of what was removed?
提问by Iain
I have an ArrayList
to be filtered, and various Guava Predicate
s to filter it with. This list will have only 50-100 elements.
我有一个ArrayList
要过滤的,还有各种 GuavaPredicate
来过滤它。此列表将只有 50-100 个元素。
I was planning on Iterables.removeIf
using each predicate in turn. It is perhaps not maximally efficient but never mind (at least removeIf
has some optimization for RandomAccess lists)
我计划Iterables.removeIf
依次使用每个谓词。它可能不是最大效率但没关系(至少removeIf
对 RandomAccess 列表进行了一些优化)
For debugging, I want to concisely log what each predicate did. e.g.
对于调试,我想简洁地记录每个谓词所做的事情。例如
Pred0 removed [a, c, g]
Pred1 removed []
Pred2 removed [b, f]
There are some obvious hack solutions but what would you suggest as the cleanest?
有一些明显的 hack 解决方案,但你认为什么是最干净的?
For bonus points, it should be reasonably efficient too. ;)
对于奖励积分,它也应该相当有效。;)
采纳答案by JanRavn
I would capture the removed elements in your Predicate code.
我会在您的 Predicate 代码中捕获已删除的元素。
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;
}
});
回答by Peter Lawrey
This may be an occasion when using a loop is simplest.
这可能是使用循环最简单的场合。
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;
}
}
回答by u290629
I guess you need:
我想你需要:
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);
回答by JB Nizet
I agree with Peter's anwser.
我同意彼得的回答。
But if you want to have fun, you could also wrap each of your predicate inside a predicate which would delegate to the wrapped predicate, and store the values for which true is returned inside a Map<Predicate, List<Foo>> removedByPredicate
:
但是,如果您想玩得开心,您也可以将每个谓词包装在一个谓词中,该谓词将委托给包装后的谓词,并将返回 true 的值存储在 a 中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;
}
}
回答by Andreas Dolk
I'd investigate in observable predicates. The idea: everytime, a predicates apply
method is about to return true, it will fire a notification to listeners:
我会在observable predicates 中进行调查。想法:每次,谓词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();
}
The ObservableLogger
is a decorator for Predicate
:
该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
}
The PredicateLogger
needs one constructor that adds itself as a listener to the predicates. It will receive the notifications and cache the predicates that fired the events (the Event
class needs an appropriate field for that information). print
will create the log message, reset
will clear the loggers cache (for the next run).
将PredicateLogger
需要一个构造函数,增加了自身作为监听到谓词。它将接收通知并缓存触发事件的谓词(Event
该类需要一个适合该信息的字段)。print
将创建日志消息,reset
将清除记录器缓存(为下一次运行)。