推薦閱讀:Java8 lambda表達式10個示例
在編程實踐中,經(jīng)常會遇到這樣的需求場景:遍歷一個列表磅废,把其中不滿足某些條件的元素刪掉纳像。
下面我們寫幾個方法來嘗試用不同的方式來實現(xiàn)這個需求:
先準備兩個校驗方法
/**
* 校驗一個字符串是否合法的方法,字符串的長度大于等于6才是合法的
*
* @param str
* @return
*/
public static boolean isValid(String str) {
if (null == str || str.length() < 6) {
return false;
}
return true;
}
public static boolean isNotValid(String str) {
return !isValid(str);
}
方式1:在for-each循環(huán)中刪除列表元素
public static void method1() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("abc");
list.add(null);
list.add("123456");
list.add("");
for (String str : list) {
if (isNotValid(str)) {
list.remove(str);
}
}
System.out.println(list);
System.out.println(list.hashCode());
}
運行上面這個方法拯勉,報異常:
java.util.ConcurrentModificationException
可見竟趾,并不能在for-each循環(huán)遍歷一個列表時去刪除這個列表的元素,此種方法行不通宫峦。
方式2:使用迭代器刪除列表元素
public static void method2() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("abc");
list.add(null);
list.add("123456");
list.add("");
System.out.println(list);
System.out.println(list.hashCode());
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String str = it.next();
if (isNotValid(str)) {
it.remove();
}
}
System.out.println(list);
System.out.println(list.hashCode());
}
運行這個方法岔帽,輸出:
[1, abc, null, 123456, ]
667562667
[123456]
1450575490
可見使用迭代器可以在遍歷列表的同時正常地刪除列表的元素,并且刪除元素之后列表的內(nèi)存地址已經(jīng)發(fā)生了變化导绷。
方式3:使用lambda表達式刪除列表元素
上面使用迭代器的方式雖然能夠正常地刪除列表中的元素犀勒,但還是不夠優(yōu)雅,因為要寫好幾行的遍歷代碼妥曲,顯得略臃腫账蓉。能不能只用一行代碼完成這個功能呢?答案是可以的——使用lambda表達式:
public static void method3() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("abc");
list.add(null);
list.add("123456");
list.add("");
System.out.println(list);
System.out.println(list.hashCode());
list.removeIf(e -> isNotValid(e));
System.out.println(list);
System.out.println(list.hashCode());
}
運行上面的方法逾一,輸出:
[1, abc, null, 123456, ]
667562667
[123456]
1450575490
可見使用lambda表達式的方法更為優(yōu)雅铸本,這里使用了List
接口所繼承的Collection
接口在JDK 1.8新增的removeIf
方法,該方法接收一個Predicate
類型的參數(shù)遵堵,刪除列表中滿足Predicate
條件的元素箱玷。在這里使用lambda表達式:e -> isNotValid(e)
定義了這樣一個Predicate
函數(shù)怨规。
方式4:使用方法引用刪除列表元素
除了lambda表達式,JDK 1.8還可以用一種稱為方法引用的方式來刪除列表中的元素锡足,使用類似C++的::
運算符波丰,來引用一個對象的實例方法或一個類的類方法,下面就用方法引用的方式來刪除一個列表中的指定元素:
public static void method4() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("abc");
list.add(null);
list.add("123456");
list.add("");
System.out.println(list);
System.out.println(list.hashCode());
list.removeIf(RemoveListElement::isNotValid); // isNotValid為RemoveListElement類的一個靜態(tài)方法
System.out.println(list);
System.out.println(list.hashCode());
}
運行上面的方法舶得,輸出:
[1, abc, null, 123456, ]
667562667
[123456]
1450575490
可見使用方法引用的方式也可以達到同樣的目的掰烟,但無疑比lambda表達式更為簡潔、優(yōu)雅沐批。
總結(jié)
經(jīng)過上述對比纫骑,可以看出:
- 在JDK 1.8之前,要使用迭代器的方式才能在遍歷一個列表的時候正確地刪除列表中的元素九孩。
- 在JDK 1.8及之后先馆,還可以使用lambda表達式和方法引用的方式正確地刪除列表中的元素,這兩種方式更為優(yōu)雅躺彬。