15

ArrayList如果满足特定条件,我想从 Java 中删除一个元素。

IE:

for (Pulse p : pulseArray) {
    if (p.getCurrent() == null) {
        pulseArray.remove(p);
    }
}

我可以理解为什么这不起作用,但是有什么好的方法呢?

4

9 回答 9

33

您可以使用Collection::removeIf(Predicate filter)(从 Java8 开始可用),这是一个简单的示例:

final Collection<Integer> list = new ArrayList<>(Arrays.asList(1, 2));
list.removeIf(value -> value < 2);
System.out.println(list); // outputs "[2]"
于 2017-12-15T13:53:35.050 回答
24

您必须使用 anIterator进行迭代和remove迭代器的功能(不是列表):

Iterator<Pulse> iter = pulseArray.iterator();
while (iter.hasNext()) {
  Pulse p = iter.next();
  if (p.getCurrent()==null) iter.remove();
}

请注意,Iterator#remove函数据说是可选的,但它由 ArrayList 的迭代器实现的。

这是 ArrayList.java 中这个具体函数的代码:

765         public void remove() {
766             if (lastRet < 0)
767                 throw new IllegalStateException();
768             checkForComodification();
769 
770             try {
771                 ArrayList.this.remove(lastRet);
772                 cursor = lastRet;
773                 lastRet = -1;
774                 expectedModCount = modCount;
775             } catch (IndexOutOfBoundsException ex) {
776                 throw new ConcurrentModificationException();
777             }
778         }
779 
780         final void checkForComodification() {
781             if (modCount != expectedModCount)
782                 throw new ConcurrentModificationException();
783         }
784     }

expectedModCount = modCount;就是为什么在迭代时使用它时它不会抛出异常的原因。

于 2012-11-09T21:57:49.420 回答
4

无需使用迭代器。使用Java 8(流和过滤功能以及 lambdas),您可以使用一行来完成它。例如。执行您指定的操作所需的代码将是:

pulseArray = pulseArray.stream().filter(pulse -> pulse != null).collect(Collectors.toList());
于 2015-10-10T14:32:56.777 回答
2

当您从同一个列表中删除元素时,索引会受到干扰。尝试如下:

  for (int i=0; i < pulseArray.size(); i++) {
     Pulse p = (Pulse)pulseArray.get(i);
     if (p.getCurrent() == null) {
        pulseArray.remove(p);
        i--;//decrease the counter by one
     }
  }
于 2012-11-09T22:02:17.950 回答
2

作为使用迭代器的替代方法,您可以使用Guava集合库。这具有更实用的优点(如果你喜欢那种东西):

Predicate<Pulse> hasCurrent = new Predicate<Pulse>() {
  @Override public boolean apply(Pulse input) {
    return (input.getCurrent() != null);
  }
};

pulseArray = Lists.newArrayList(Collections2.filter(pulseArray, hasCurrent));
于 2012-11-09T23:11:14.770 回答
2

您可以实现接口 Predicate 覆盖抽象方法boolean test(T);

使用removeIf(Predicate p)方法从列表中删除所有匹配的元素。

例如:

List<Book> bookList = new ArrayList<>();
bookList.add(new Book(101, "bookname1"));
bookList.add(new Book(102, "booknamelong2"));
bookList.removeIf(new LongBookNames())

public class LongBookNames implements Predicate<Book> {

  @Override
  public boolean test(Book book) {
    return book.getBookName.length() >10;
  }
}
于 2021-03-21T12:30:19.537 回答
0

您不能使用集合上的方法更改正在迭代的集合。但是,一些迭代器(包括ArrayLists 上的迭代器)支持一种remove()方法,该方法允许您按照迭代的顺序删除方法。

Iterator<Pulse> iterator = pulseArray.iterator();
while (iterator.hasNext()) {
  Pulse p = iterator.next();
  if (p.getCurrent() == null) {
    iterator.remove();
  }
}
于 2012-11-09T21:59:41.547 回答
0

当 Single ArrayList 有多种类型 Objects 并且一个对象的 count == 0 时使用下面的一个,然后它从pulseArray中删除

常量.java

public class ViewType {
    public static final int PULSE = 101;
    public static final int HEARTBEAT = 102;
}

BaseModel.java(这是基本模型)

public interface BaseModel {
    int getViewType();
}

PulseModel.java(使用 BaseModel 实现)

public class PulseModel implements BaseModel {

    @Override
    public int getViewType() {
        return Constants.ViewType.PULSE;
    }

    @SerializedName("PulseId")
    @Expose
    private String pulseId;
    @SerializedName("Count")
    @Expose
    private String count;
}

从Count = 0的pulseArray中删除 PulseModel 对象

pulseArray.removeIf(
     (BaseModel model) -> {
         boolean remove = false;
         if (model instanceof PulseModel) {
              remove = (((PulseModel) model).getCount() == 0);
              if (remove) {
                 //Success
              }
         }
         return remove;
      });
于 2021-04-28T11:05:28.417 回答
-2

使用 Iterator 可以让您在遍历 arraylist 时修改列表

于 2012-11-09T22:39:55.123 回答