在Java中过滤元素的简单方法?

Fre*_*rik 21 java collections

我想编写一个方法,从一个集合中删除遵循某种模式的所有元素.在函数式语言中,我会使用带有lambda表达式的filter().但是,在Java中,似乎我坚持这样:

public void removeAllBlueCars() {
    LinkedList<Car> carsToRemove = new LinkedList<Car>();
    for (Car c : cars) {
        if (c.getCarColor() == Color.BLUE) {
            carsToRemove.add(c);
        }
    }
    cars.removeAll(carsToRemove );
}
Run Code Online (Sandbox Code Playgroud)

直接删除元素会导致ConcurrentModificationException.有没有更好的方法来做到这一点,而不诉诸谷歌收藏

Jef*_*oom 17

使用Java 8,您可以使用lambda表达式进行过滤Collection.removeIf.

cars.removeIf(c -> c.getCarColor() == Color.BLUE);
Run Code Online (Sandbox Code Playgroud)


Pét*_*rök 14

您可以使用ListIterator具有remove方法的a遍历列表.

顺便说一句,你应该将你的列表声明为List<Car>- 接口程序,而不是实现.

  • `Iterator`已经有`remove`方法. (3认同)

Viv*_*sse 13

也许你可以使用更高效的迭代器:

public void removeAllBlueCars() {
    Iterator<Car> carsIterator = cars.iterator();
    while (carsIterator.hasNext()) {
        Car c = carsIterator.next();
        if (c.getCarColor() == Color.BLUE) {
            carsIterator.remove();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,如果你想让这个解决方案更通用,我会建议你:

public interface Filter<T> {

    public boolean shouldRemove(T t);

}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

public void removeCars(Filter<Car> filter) {
    Iterator<Car> carsIterator = cars.iterator();
    while (carsIterator.hasNext()) {
        Car c = carsIterator.next();
        if (filter.shouldRemove(c)) {
            carsIterator.remove();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您的方法被调用如下:

removeCars(new Filter<Car>() {

    public boolean shouldRemove(Car car) {
        return car.getCarColor() == Color.BLUE;
    }

});
Run Code Online (Sandbox Code Playgroud)


gpe*_*che 5

您可以使用CollectionUtils.filter()。它与 an 一起使用Iterator,因此直接从 中删除项目应该没有问题Collection。但这是另一种依赖。如果你想要独立的代码,那就是:

public interface Predicate {
    boolean evaluate(Object o);
}

public static void filter(Collection collection, Predicate predicate) {
if ((collection != null) && (predicate != null))
    for (Iterator it = collection.iterator(); it.hasNext(); )
        if (!predicate.evaluate(it.next()))
            it.remove();
}
...
filter(collection, new Predicate() {
    public boolean evaluate(Object o) { return whatever; }
});
Run Code Online (Sandbox Code Playgroud)