番石榴 - 如何从列表中删除,基于谓词,跟踪删除的内容?

Iai*_*ain 17 java collections filtering predicate guava

我有一个ArrayList要过滤,并用各种番石榴Predicate来过滤它.此列表只有50-100个元素.

我打算Iterables.removeIf依次使用每个谓词.它可能不是最大效率但从不介意(至少removeIf对RandomAccess列表有一些优化)

对于调试,我想简明地记录每个谓词的作用.例如

Pred0 removed [a, c, g]
Pred1 removed []
Pred2 removed [b, f]
Run Code Online (Sandbox Code Playgroud)

有一些明显的黑客解决方案,但你认为最干净的是什么?

对于奖励积分,它也应该是合理有效的.;)

Jan*_*avn 32

我会捕获您的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;
    }
}); 
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这也是我最终的结果 - 我喜欢它的简洁性.我确信谓词不是100%犹太教,因为谓词有副作用,但我并不在乎(如果我们关心的话,我们可以使它成为幂等的) (3认同)

Pet*_*rey 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;
       }
 }
Run Code Online (Sandbox Code Playgroud)

  • `Multimap <Predicate,MyType>`也会使事情变得更加简洁. (4认同)