在接下來的階段中,將和你們分享Java 8 系列的一些知識點。本文和你們講述Predicate的使用方法介紹以及其背景。bash
首先,讓咱們看看如何使用簡單的filter()
來過濾一個List集合:spa
@Test
public void whenFilterList(){
List<String> names = Arrays.asList("Apps", "Alibaba", "william", "Son");
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Apps","Alibaba"));
}
複製代碼
在此示例中,咱們過濾了List集合,保留以「A」開頭的數據 :code
name -> name.startsWith("A")
複製代碼
可是假如須要過濾多個條件的話,應該如何?cdn
若是咱們想要應用多個過濾,一個比較簡單地方式就是設置多個過濾器:blog
@Test
public void whenFilterListWithMultiple(){
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.filter(name -> name.length() < 5)
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Apps"));
}
複製代碼
看上面的示例,經過提取以「A」開頭而且長度小於5的數據來過濾咱們的集合。ip
咱們使用了兩個過濾條件。string
如今,咱們能夠使用一個帶有複雜的過濾器,而不是使用多個過濾器filer()
:it
@Test
public void whenFilterListWithComplexPredicate(){
List<String> result = names.stream()
.filter(name -> name.startsWith("A") && name.length() < 5)
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
複製代碼
這個改進比第一個更靈活,由於咱們能夠使用按位運算來構建咱們想要的複雜語句。io
接下來,若是咱們不想使用按位運算構建複雜語句,Java 8 Predicate能夠使用有用的方法來組合過濾條件。function
咱們將使用Predicate.and()
,Predicate.or()
和Predicate.negate()
方法組合Predicates。
咱們來看看只用 and()
的方式,能夠怎麼用
@Test
public void whenFilterListWithCombinedPredicatesUsingAnd(){
Predicate<String> predicate1 = str -> str.startsWith("A");
Predicate<String> predicate2 = str -> str.length() < 5;
List<String> result = names.stream()
.filter(predicate1.and(predicate2))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
複製代碼
這樣的語法很是直觀,方法名稱代表了操做的類型。使用and()
,咱們經過僅提取知足兩個條件的名稱來過濾咱們的List。
接下來,咱們看看or()
的方式使用。條件爲w開頭
、或者長度小於4
;
@Test
public void whenFilterListWithCombinedPredicatesUsingOr(){
Predicate<String> predicate1 = str -> str.startsWith("w");
Predicate<String> predicate2 = str -> str.length() < 4;
List<String> result = names.stream()
.filter(predicate1.or(predicate2))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("John","Tom"));
}
複製代碼
如今咱們來結合一下看看 negate()
的使用場景,這個方法是指相反條件,即 <>
,!xxx
。
@Test
public void whenFilterListWithCombinedPredicatesUsingOrAndNegate(){
Predicate<String> predicate1 = str -> str.startsWith("w");
Predicate<String> predicate2 = str -> str.length() < 4;
List<String> result = names.stream()
.filter(predicate1.or(predicate2.negate()))
.collect(Collectors.toList());
assertEquals(3, result.size());
assertThat(result, contains("Apps","Alibaba","william"));
}
複製代碼
上示例的代碼中,條件是爲 w開頭的或者 數據的長度不是小於4的過濾條件。
咱們甚至也能夠不用寫 and()、or()、negate()就能夠使用predicate方法:
@Test
public void whenFilterListWithCombinedPredicatesInline(){
List<String> result = names.stream()
.filter(((Predicate<String>)name -> name.startsWith("A"))
.and(name -> name.length()<5))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Apps"));
}
複製代碼
最後,讓咱們看看如何經過編寫出一個能夠支持多個複雜條件的過濾方法。
在下面的例子中,咱們有一個列表集合,咱們使用組合Predicate.and() :
@Test
public void whenFilterListWithCollectionOfPredicatesUsingAnd(){
List<Predicate<String>> allPredicates = new ArrayList<Predicate<String>>();
allPredicates.add(str -> str.startsWith("A"));
allPredicates.add(str -> str.contains("ba"));
allPredicates.add(str -> str.length() > 4);
List<String> result = names.stream()
.filter(allPredicates.stream().reduce(x->true, Predicate::and))
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Alibaba"));
}
複製代碼
請留意,咱們使用了一個關鍵性代碼:
x->true
複製代碼
可是若是咱們想要使用Predicate.or()
組合它們會有所不一樣:
@Test
public void whenFilterListWithCollectionOfPredicatesUsingOr(){
List<String> result = names.stream()
.filter(allPredicates.stream().reduce(x->false, Predicate::or))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Apps","Alibaba"));
}
複製代碼
本文主要是講解了如何更好的過濾List中的數據,filter()
、Predicates
的使用方法,已經針對的場景。