フィルタリングするArrayList
と、フィルタリングするさまざまなGuava Predicate
sがあります。このリストには、50〜100個の要素のみが含まれます。
私は、各述語を順番に使用してIterables.removeIf
を計画していました。おそらく最大限に効率的ではありませんが、気にしないでください(少なくともremoveIf
にはRandomAccessリストの最適化があります)
デバッグのために、各述語が行ったことを簡潔にログに記録したいと思います。例えば.
Pred0 removed [a, c, g]
Pred1 removed []
Pred2 removed [b, f]
明らかなハッキングソリューションがいくつかありますが、最もクリーンなものとして何を提案しますか?
ボーナスポイントについても、かなり効率的である必要があります。 ;)
削除された要素を述語コードでキャプチャします。
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;
}
});
これは、ループの使用が最も簡単な場合です。
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;
}
}
観察可能な述語で調査します。アイデア:述語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
には、述語にリスナーとして自分自身を追加する1つのコンストラクターが必要です。通知を受信し、イベントを発生させた述語をキャッシュします(Event
クラスにはその情報に適切なフィールドが必要です)。 print
はログメッセージを作成し、reset
はロガーキャッシュをクリアします(次の実行のために)。
私はピーターの答えに同意します。
ただし、楽しみたい場合は、各述語を、ラップされた述語に委任する述語内にラップし、trueが返される値を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;
}
}