Collection之removeif()方法使用
錯誤示範:
在集合框架的使用中,經常會有遍歷中需要添加元素或者刪除元素的情況出現,如果使用此方法
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
for (Integer i : list) {
//當i是偶數就刪除此元素
if (i % 2 == 0) {
list.remove(i);
}
}
運行時會出現
Exception in thread "main" java.util.ConcurrentModificationException
api中是這樣解釋的
當不允許這樣的修改時,可以通過檢測到對象的併發修改的方法來拋出此異常。
例如,一個線程通常不允許修改集合,而另一個線程正在遍歷它。 一般來說,在這種情況下,迭代的結果是未定義的。 某些迭代器實現(包括由JRE提供的所有通用集合實現的實現)可能會選擇在檢測到此行爲時拋出此異常。 這樣做的迭代器被稱爲故障快速迭代器,因爲它們快速而乾淨地失敗,而是在未來未確定的時間冒着任意的非確定性行爲。
請注意,此異常並不總是表示對象已被不同的線程同時修改。 如果單個線程發出違反對象合同的方法調用序列,則該對象可能會拋出此異常。 例如,如果線程在使用故障快速迭代器迭代集合時直接修改集合,則迭代器將拋出此異常。
請注意,故障快速行爲無法保證,因爲一般來說,在不同步併發修改的情況下,無法做出任何硬性保證。 失敗快速的操作儘可能地拋出
ConcurrentModificationException
。 因此,編寫依賴於此異常的程序的正確性將是錯誤的: ConcurrentModificationException應僅用於檢測錯誤。
簡單的說就是在遍歷的過程中對集合進行修改就會拋出此異常.
正確方法:
改進的方法有兩種:
使用迭代器:
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i % 2 == 0) {
list.remove(i);
}
}
遍歷完後再刪除:
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
ArrayList<Integer> list02 = new ArrayList<>();
for (Integer i : list) {
if (i % 2 == 0) {
list02.add(i);
}
}
list.removeAll(list02);
System.out.println(list);
都是比較麻煩的.
使用removeIf(Predicate<? super E> filter)
方法改進:
在JDK1.8中,
Collection
中加入了removeIf
方法,其子類自然也繼承了此方法
default boolean
removeIf(Predicate<? super E> filter)
刪除滿足給定謂詞的此集合的所有元素。
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
//只需一行代碼
//使用此方法刪除list集合中滿足過濾條件的元素
list.removeIf(integer -> integer % 2 == 0);
System.out.println(list);
可以看到,使用removeIf
()方法後,原來需要最多7行的代碼變成了一行!
以下爲部分源碼
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
可以看到底層源碼也是使用迭代器的,和上一步的方法原理相同,所以推薦使用此更方便,精簡的方法