Java8述語チェーン
1. 概要
このクイックチュートリアルでは、Java8で述語をチェーンするさまざまな方法について説明します。
2. 基本例
まず、単純な述語を使用して、名前のリストをフィルタリングする方法を見てみましょう。
@Test
public void whenFilterList_thenSuccess(){
List<String> names = Arrays.asList("Adam", "Alexander", "John", "Tom");
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Adam","Alexander"));
}
この例では、名前の List をフィルタリングして、Predicateを使用して「A」で始まる名前のみを残しました。
name -> name.startsWith("A")
しかし、複数の述語を適用したい場合はどうでしょうか。
3. 複数のフィルター
複数の述語、を適用したい場合、1つのオプションは、複数のフィルターを単純にチェーンすることです。
@Test
public void whenFilterListWithMultipleFilters_thenSuccess(){
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("Adam"));
}
ここで、例を更新して、「A」で始まり、長さが5未満の名前を抽出してリストをフィルタリングします。
述語ごとに1つずつ、合計2つのフィルターを使用しました。
4. 複雑な述語
これで、複数のフィルターを使用する代わりに、複雑な述語を持つ1つのフィルターを使用できます:
@Test
public void whenFilterListWithComplexPredicate_thenSuccess(){
List<String> result = names.stream()
.filter(name -> name.startsWith("A") && name.length() < 5)
.collect(Collectors.toList());
assertEquals(1, result.size());
assertThat(result, contains("Adam"));
}
このオプションは最初のオプションよりも柔軟性があります。ビット演算を使用して、必要に応じて複雑な述語を作成できるためです。
5. 述語の組み合わせ
次に、ビット演算を使用して複雑な述語を作成したくない場合、Java 8 述語には、述語を組み合わせるために使用できる便利なメソッドがあります。 。
メソッドPredicate.and()、 Predicate.or()、および Predicate.negate()。を使用して、Predicatesを結合します。 ]
5.1. Predicate.and()
この例では、 Predicates を明示的に定義してから、 Predicate.and():を使用してそれらを結合します。
@Test
public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){
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"));
}
ご覧のとおり、構文はかなり直感的であり、メソッド名は操作のタイプを示しています。 と()を使用して、両方の条件を満たす名前のみを抽出することにより、リストをフィルタリングしました。
5.2. Predicate.or()
Predicate.or()を使用して、Predicates。を結合することもできます。
「J」で始まる名前と、長さが4未満の名前を抽出してみましょう。
@Test
public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){
Predicate<String> predicate1 = str -> str.startsWith("J");
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"));
}
5.3. Predicate.negate()
Predicates を組み合わせる場合も、 Predicate.negate()を使用できます。
@Test
public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){
Predicate<String> predicate1 = str -> str.startsWith("J");
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("Adam","Alexander","John"));
}
ここでは、 or()と negate()の組み合わせを使用して、Listを「J」で始まる名前または長さのある名前でフィルタリングしました。それは4以上です。
5.4. 述語インラインを組み合わせる
and()、 or()、および negate()。を使用するために、述語を明示的に定義する必要はありません。
述語をキャストしてインラインで使用することもできます。
@Test
public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){
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("Adam"));
}
6. 述語のコレクションを組み合わせる
最後に、述語のコレクションを減らして連鎖させる方法を見てみましょう。
次の例では、 Predicate.and()を使用して結合したPredicatesのListがあります。
@Test
public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){
List<Predicate<String>> allPredicates = new ArrayList<Predicate<String>>();
allPredicates.add(str -> str.startsWith("A"));
allPredicates.add(str -> str.contains("d"));
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("Alexander"));
}
基本IDを次のように使用することに注意してください。
x->true
ただし、 Predicate.or()を使用してそれらを組み合わせる場合は異なります。
@Test
public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){
List<String> result = names.stream()
.filter(allPredicates.stream().reduce(x->false, Predicate::or))
.collect(Collectors.toList());
assertEquals(2, result.size());
assertThat(result, contains("Adam","Alexander"));
}
7. 結論
この記事では、 filter()、複合述語を使用し、述語を組み合わせることにより、Java8で述語をチェーンするさまざまな方法を検討しました。
完全なソースコードは、GitHubでから入手できます。