开发者

Collections removeAll method

I would like to know if something lik开发者_JAVA百科e below is possible,

list.removeAll(namesToRemove)

I hope the context is understandable.

The list is of type ArrayList<MyObject> where MyObject has a getName method.

The namesToRemove is an ArrayList<String> containing names of the objects to be removed.

I know this can be achieved by overriding equals method in MyObject class. I would like to know if any other choice is present.


You can do something like this using Google Collections Collections2.filter():

final List<String> namesToKeep = getNamesToFilter();
List<MyObject> filtered = Collections2.filter(originalList, new Predicate<MyObject>() {
  @Override
  public boolean apply(MyObject o) {
    return namesToKeep.contains(o.getName());
  }
});


Java 8:

list.removeIf(obj -> namesToRemove.contains(obj.getName()));

Java 7 and older:

Iterator<MyObject> iter = list.iterator();
while (iter.hasNext())
    if (namesToRemove.contains(iter.next().getName()))
        iter.remove();

Note that both alternatives have quadratic complexity. You can make it linear by doing

Set<String> namesToRemoveSet = new HashSet<>(namesToRemove);

before the snippets, and use namesToRemoveSet instead of namesToRemove.


You don't want to override anything in the Object class. You need to use either a filter utility or a collection that uses your own semantics instead of equals, maybe a ForwardingCollection wrapped around your own implementation of equivalence.

All this can be achieved with google guava without breaking any standards


Another approach: Subclass ArrayList and implement a custom method like:

public class MyArrayList<E> extends ArrayList<E> {

   // all needed constructors

   public void removeAllWithNames(Collection<String> names) {
     // following code is based on aioobe's answer
     Iterator<E> iter = iterator();
       while (iter.hasNext())
         if (names.contains(iter.next().toString()))
           iter.remove();
   }
}

EDIT changed the code - the comment was good, now the custom list is a 'List' again, but now we use the toString() method (for simplicity) for filtering. (using a getName() method is possible but requires more lines of code)


Collection<MyObject> list = Collections2.filter(list, mo -> !namesToRemove.contains(mo.getName()));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜