Java 8述語チェーン

Java 8述語チェーン

1. 概要

このクイックチュートリアルでは、we’ll discuss different ways to chain Predicates in Java 8.

2. 基本的な例

まず、let’s see how to use a simple Predicateを使用して、Listの名前をフィルタリングします。

@Test
public void whenFilterList_thenSuccess(){
   List names = Arrays.asList("Adam", "Alexander", "John", "Tom");
   List 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")

しかし、複数のPredicatesを適用したい場合はどうでしょうか。

3. 複数のフィルター

複数のPredicatesを適用したい場合は、one option is to simply chain multiple filters:

@Test
public void whenFilterListWithMultipleFilters_thenSuccess(){
    List 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未満の名前を抽出してリストをフィルタリングするようにしました。

Predicateごとに1つずつ、合計2つのフィルターを使用しました。

4. 複雑なPredicate

これで、複数のフィルターを使用する代わりに、we can use one filter with a complex Predicate:

@Test
public void whenFilterListWithComplexPredicate_thenSuccess(){
    List result = names.stream()
      .filter(name -> name.startsWith("A") && name.length() < 5)
      .collect(Collectors.toList());

    assertEquals(1, result.size());
    assertThat(result, contains("Adam"));
}

このオプションは、we can use bitwise operations to build the Predicateが必要なだけ複雑であるため、最初のオプションよりも柔軟性があります。

5. Predicatesを組み合わせる

次に、ビット演算を使用して複雑なPredicateを作成したくない場合、Java 8Predicateには、Predicatesを組み合わせるために使用できる便利なメソッドがあります。

メソッドPredicate.and()Predicate.or()、およびPredicate.negate().を使用してPredicatesを結合します

5.1. Predicate.and()

この例では、Predicatesを明示的に定義してから、Predicate.and():を使用してそれらを結合します。

@Test
public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){
    Predicate predicate1 =  str -> str.startsWith("A");
    Predicate predicate2 =  str -> str.length() < 5;

    List result = names.stream()
      .filter(predicate1.and(predicate2))
      .collect(Collectors.toList());

    assertEquals(1, result.size());
    assertThat(result, contains("Adam"));
}

ご覧のとおり、構文はかなり直感的であり、メソッド名は操作のタイプを示しています。 and()を使用して、両方の条件を満たす名前のみを抽出することにより、Listをフィルタリングしました。

5.2. Predicate.or()

Predicate.or()を使用してPredicates.を結合することもできます

「J」で始まる名前と、4未満の長さの名前を抽出してみましょう。

@Test
public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){
    Predicate predicate1 =  str -> str.startsWith("J");
    Predicate predicate2 =  str -> str.length() < 4;

    List 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 predicate1 =  str -> str.startsWith("J");
    Predicate predicate2 =  str -> str.length() < 4;

    List result = names.stream()
      .filter(predicate1.or(predicate2.negate()))
      .collect(Collectors.toList());

    assertEquals(3, result.size());
    assertThat(result, contains("Adam","Alexander","John"));
}

ここでは、or()negate()の組み合わせを使用して、「J」で始まる名前または4以上の長さの名前でListをフィルタリングしました。

5.4. Predicatesをインラインで組み合わせる

and(),or()、およびnegate().を使用するために、Predicatesを明示的に定義する必要はありません。

Predicateをキャストすることで、それらをインラインで使用することもできます。

@Test
public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){
    List result = names.stream()
      .filter(((Predicate)name -> name.startsWith("A"))
      .and(name -> name.length()<5))
      .collect(Collectors.toList());

    assertEquals(1, result.size());
    assertThat(result, contains("Adam"));
}

6. Predicatesのコレクションを組み合わせる

最後に、let’s see how to chain a collection of Predicates by reducing them.

次の例では、Predicate.and()を使用して結合したPredicatesListがあります。

@Test
public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){
    List> allPredicates = new ArrayList>();
    allPredicates.add(str -> str.startsWith("A"));
    allPredicates.add(str -> str.contains("d"));
    allPredicates.add(str -> str.length() > 4);

    List 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 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(),を使用して複雑なPredicatesを構築し、Predicates.を組み合わせることにより、Java8で述語をチェーンするさまざまな方法を検討しました。

完全なソースコードはover on GitHubで入手できます。