用Java从集合中筛选元素的简单方法?

用Java从集合中筛选元素的简单方法?,java,collections,Java,Collections,我想写一个方法,从遵循特定模式的集合中删除所有元素。在函数式语言中,我将使用带有lambda表达式的filter()。然而,在Java中,我似乎被以下问题所困扰: public void removeAllBlueCars() { LinkedList<Car> carsToRemove = new LinkedList<Car>(); for (Car c : cars) { if (c.getCarColor() == Color.BL

我想写一个方法,从遵循特定模式的集合中删除所有元素。在函数式语言中,我将使用带有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 );
}
public void removeAllBlueCars(){
LinkedList carsToRemove=新建LinkedList();
用于(c车:汽车){
if(c.getCarColor()==Color.BLUE){
carsToRemove.add(c);
}
}
cars.removeAll(carsToRemove);
}

删除元素直接导致ConcurrentModificationException。有没有更好的方法不用求助于?

您可以使用具有方法的迭代遍历列表


顺便说一句,您应该将列表声明为接口程序,而不是实现程序。

查看的过滤器选项是否可以帮助您

也许您可以使用迭代器,它的效率更高一些:

public void removeAllBlueCars() {
    Iterator<Car> carsIterator = cars.iterator();
    while (carsIterator.hasNext()) {
        Car c = carsIterator.next();
        if (c.getCarColor() == Color.BLUE) {
            carsIterator.remove();
        }
    }
}
public void removeAllBlueCars(){
迭代器carsIterator=cars.Iterator();
while(carsIterator.hasNext()){
Car c=carsIterator.next();
if(c.getCarColor()==Color.BLUE){
carsIterator.remove();
}
}
}

此外,如果您想使此解决方案更通用,我建议您采取以下措施:

public interface Filter<T> {

    public boolean shouldRemove(T t);

}
公共接口过滤器{
公共布尔值应删除(T);
}
你可以这样使用它:

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

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

});
public void removeCars(过滤器){
迭代器carsIterator=cars.Iterator();
while(carsIterator.hasNext()){
Car c=carsIterator.next();
如果(过滤器应移除(c)){
carsIterator.remove();
}
}
}
您的方法的调用方式如下:

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

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

});
removeCars(新过滤器(){
公共布尔值应移除(汽车){
return car.getCarColor()==Color.BLUE;
}
});

您可以随时后退并删除元素

    for (int i = array.size() - 1; i >= 0; i--) {
       if (array.get(i).getCarColor() == Color.BLUE)
                array.remove(i);
    }
编辑:注意到这是一个链接列表,可能会使我的答案有点不相关。

您可以使用。它与
迭代器一起工作
,因此直接从
集合
中删除项应该没有问题。但这是另一种依赖。如果您希望代码独立,它将是:

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; }
});

我非常喜欢Vivien Barousse和gpeche提供的迭代器解决方案。但我想指出的是,实际上不必从集合中删除任何元素,只需防止过滤器返回它们。这样,您基本上可以拥有同一集合的多个视图,这非常方便和高效。Filter对象基本上是您的lamda表达式,或者在版本7之前您将在Java中得到的最接近的对象…

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


对于那些遇到此线程并可能正在使用RxJava/RxAndroid的Android上工作的人,有一种不添加Apache Commons Collections依赖项的快速方法:

cars = Observable.from(cars).filter(car -> {
  if (car.getCarColor() == Color.BLUE) {
    return false;
  }

  return true;
}).toList().toBlocking().first();
注意,我还碰巧将lambda表达式用于。如果不使用Retrolambda,可以使用以下表达式表达相同的内容:

cars = Observable.from(cars).filter(new Func1<Car, Boolean>() {
      @Override
      public Boolean call(Car car) {
        if (car.getCarColor() == Color.BLUE) {
          return false;
        }

        return true;
      }
}).toList().toBlocking().first();
cars=Observable.from(cars).filter(new Func1()){
@凌驾
公共布尔呼叫(汽车){
if(car.getCarColor()==Color.BLUE){
返回false;
}
返回true;
}
}).toList().toBlocking().first();

这确实是一篇老文章,但是如何使用Oracle Java教程中给出的方法进行abt

static void filter(Collection<?>c) {
    for (Iterator<?>it = c.iterator(); it.hasNext(); )
         if (!cond(it.next()))
             it.remove();
}
静态空隙过滤器(Collectionc){
for(Iteratorit=c.iterator();it.hasNext();)
如果(!cond(it.next()))
it.remove();
}

以下是Android实现通用解决方案的方法:

用法: 从我的列表中删除所有空字符串

    LinkedList<String> list = ...
    ListUtils.filter(list, new ListUtils.Filter<String>() {
        @Override
        public boolean keepItem(String item) {
            return item != null;
        }
    });
LinkedList=。。。
ListUtils.filter(列表,新的ListUtils.filter(){
@凌驾
公共布尔keepItem(字符串项){
退货项目!=空;
}
});
资料来源:
公共类ListUtils{
公共接口过滤器{
布尔keepItem(T项);
}
公共静态无效筛选器(@NonNull列表项,@NonNull筛选器){
for(Iterator Iterator=items.Iterator();Iterator.hasNext();){
if(!filter.keepItem(iterator.next())){
iterator.remove();
}
}
}
}
公共静态void filter(列表,谓词随着Java8的引入,以更具功能性的方法在集合上实现过滤要容易得多

我为您编写了一个示例。还请注意,使用forEach打印收藏内容是多么好:

public class Java8Filtering {

    public static void main(String[] argc) {
        LinkedList<Car> cars = new LinkedList<>();
        cars.add(new Car("car 1", Color.BLUE));
        cars.add(new Car("car 2", Color.GREEN));
        cars.add(new Car("car 3", Color.RED));
        cars.add(new Car("car 4", Color.BLUE));

        List<Car> filteredCars = cars.stream()
                .filter(car -> car.getCarColor() != Color.BLUE)
                .collect(Collectors.toList());

        filteredCars.forEach(car -> System.out.println("Car: " + car.getCarName() + " with color: " + car.getCarColor()));
    }
}

class Car {

    private Color carColor;
    private String carName;

    public Car(String carName, Color carColor) {
        this.carName = carName;
        this.carColor = carColor;
    }

    public Color getCarColor() {
        return carColor;
    }

    public void setCarColor(Color carColor) {
        this.carColor = carColor;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }
}

enum Color {
    BLUE, GREEN, RED
}
公共类Java8Filtering{
公共静态void main(字符串[]argc){
LinkedList cars=新建LinkedList();
添加(新车(“1号车”,颜色为蓝色));
添加(新车(“2号车”,颜色为绿色));
添加(新车(“3号车”,颜色为红色));
添加(新车(“4号车”,颜色为蓝色));
List filteredCars=cars.stream()
.filter(car->car.getCarColor()!=Color.BLUE)
.collect(Collectors.toList());
filteredCars.forEach(car->System.out.println(“car:+car.getCarName()+”带颜色:“+car.getCarColor()));
}
}
班车{
私人色彩;
私弦肉桂;
公共汽车(字符串carName、彩色carColor){
this.carName=carName;
this.carColor=carColor;
}
公共颜色getCarColor(){
返回颜色;
}
公共无效设置carColor(颜色carColor){
this.carColor=carColor;
}
公共字符串getCarName(){
返回卡尔纳姆;
}
公共无效setCarName(字符串carName){
this.carName=carName;
}
}
枚举颜色{
蓝色,绿色,红色
}

为什么你不想使用google collections?顺便说一句,是新的google collections吗?我喜欢google collections/Guava,但我的问题是,你要知道如何做到这一点,而不必重复
public class Java8Filtering {

    public static void main(String[] argc) {
        LinkedList<Car> cars = new LinkedList<>();
        cars.add(new Car("car 1", Color.BLUE));
        cars.add(new Car("car 2", Color.GREEN));
        cars.add(new Car("car 3", Color.RED));
        cars.add(new Car("car 4", Color.BLUE));

        List<Car> filteredCars = cars.stream()
                .filter(car -> car.getCarColor() != Color.BLUE)
                .collect(Collectors.toList());

        filteredCars.forEach(car -> System.out.println("Car: " + car.getCarName() + " with color: " + car.getCarColor()));
    }
}

class Car {

    private Color carColor;
    private String carName;

    public Car(String carName, Color carColor) {
        this.carName = carName;
        this.carColor = carColor;
    }

    public Color getCarColor() {
        return carColor;
    }

    public void setCarColor(Color carColor) {
        this.carColor = carColor;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }
}

enum Color {
    BLUE, GREEN, RED
}