Groovyでコレクション内の要素を見つける

  • link:/category/programming/ [プログラミング]

  • Groovy

1. 前書き

link:/groovy-language[Groovy]は、Javaのコア機能を強化する多数のメソッドを提供します。
このチュートリアルでは、要素をチェックし、https://www.baeldung.com/groovy-lists [いくつかのタイプのコレクション]でそれを見つけるときにGroovyがこれを行う方法を示します。*

2. 要素が存在するかどうかをテスト

まず、特定のコレクションに要素が含まれているかどうかをテストすることに焦点を当てます。

* 2.1。 リスト*

Java自体は、java.util.List *を使用してリスト内の項目を*チェックする方法をいくつか提供します。
  • _contains_メソッド

  • indexOf methodメソッド

    GroovyはJava互換言語なので、安全に使用できます。
    例を見てみましょう:
@Test
void whenListContainsElement_thenCheckReturnsTrue() {
    def list = ['a', 'b', 'c']

    assertTrue(list.indexOf('a') > -1)
    assertTrue(list.contains('a'))
}
それとは別に、* Groovyはメンバーシップ演算子を導入します:*
element in list
これは、Groovyが提供する多くの構文シュガー演算子の1つです。 その助けを借りて、コードを単純化できます。
@Test
void whenListContainsElement_thenCheckWithMembershipOperatorReturnsTrue() {
    def list = ['a', 'b', 'c']

    assertTrue('a' in list)
}

* 2.2。 Set*

前の例と同様に、_java.util.Set#contains_メソッドと_in_演算子を使用できます。
@Test
void whenSetContainsElement_thenCheckReturnsTrue() {
    def set = ['a', 'b', 'c'] as Set

    assertTrue(set.contains('a'))
    assertTrue('a' in set)
}

* 2.3。 Map*

_Map_の場合、キーまたは値のいずれかを直接確認できます。
@Test
void whenMapContainsKeyElement_thenCheckReturnsTrue() {
    def map = [a: 'd', b: 'e', c: 'f']

    assertTrue(map.containsKey('a'))
    assertFalse(map.containsKey('e'))
    assertTrue(map.containsValue('e'))
}
または、メンバーシップ演算子を使用して、一致するキーを見つけます。
@Test
void whenMapContainsKeyElement_thenCheckByMembershipReturnsTrue() {
    def map = [a: 'd', b: 'e', c: 'f']

    assertTrue('a' in map)
    assertFalse('f' in map)
}
マップで使用する場合、メンバーシップ演算子は注意して使用する必要があります*この演算子はブール値との使用が少し混乱するためです* *ブール値にキャストします:*
@Test
void whenMapContainsFalseBooleanValues_thenCheckReturnsFalse() {
    def map = [a: true, b: false, c: null]

    assertTrue(map.containsKey('b'))
    assertTrue('a' in map)
    assertFalse('b' in map)
    assertFalse('c' in map)
}
上記の例で見られるように、同じ理由で_null_値で使用するのは少し危険です*。 Groovyは、_false_と_null_の両方をブール値_false_にキャストします。

3. すべて一致および任意一致

ほとんどの場合、より複雑なオブジェクトで構成されるコレクションを扱います。 このセクションでは、指定されたコレクションに少なくとも1つの一致する要素が含まれているかどうか、またはすべての要素が指定された述語と一致しているかどうかを確認する方法を示します。
例で使用する単純なクラスを定義することから始めましょう。
class Person {
    private String firstname
    private String lastname
    private Integer age

    // constructor, getters and setters
}

* 3.1。 リスト/セット*

今回は、simple_Person_オブジェクトの単純なリストを使用します。
private final personList = [
  new Person("Regina", "Fitzpatrick", 25),
  new Person("Abagail", "Ballard", 26),
  new Person("Lucian", "Walter", 30),
]
前述したように、* GroovyはJava互換言語*なので、最初にJava 8で導入されたlink:/java-8-streams-introduction[_Stream_ API]を使用して例を作成しましょう。
@Test
void givenListOfPerson_whenUsingStreamMatching_thenShouldEvaluateList() {
    assertTrue(personList.stream().anyMatch {it.age > 20})
    assertFalse(personList.stream().allMatch {it.age < 30})
}
コレクションで直接チェックを実行するGroovyメソッド__DefaultGroovyMethods#any __and __DefaultGroovyMethods#every __を使用することもできます。
@Test
void givenListOfPerson_whenUsingCollectionMatching_thenShouldEvaluateList() {
    assertTrue(personList.any {it.age > 20})
    assertFalse(personList.every {it.age < 30})
}

* 3.2。 Map*

_Person#firstname_によってマップされた__Person ___objectsの_Map_を定義することから始めましょう:
private final personMap = [
  Regina : new Person("Regina", "Fitzpatrick", 25),
  Abagail: new Person("Abagail", "Ballard", 26),
  Lucian : new Person("Lucian", "Walter", 30)
]
キー、値、またはエントリ全体で評価できます。 繰り返しますが、最初に_Stream_ APIを使用しましょう。
@Test
void givenMapOfPerson_whenUsingStreamMatching_thenShouldEvaluateMap() {
    assertTrue(personMap.keySet().stream().anyMatch {it == "Regina"})
    assertFalse(personMap.keySet().stream().allMatch {it == "Albert"})
    assertFalse(personMap.values().stream().allMatch {it.age < 30})
    assertTrue(personMap.entrySet().stream().anyMatch
      {it.key == "Abagail" && it.value.lastname == "Ballard"})
}
*そして、Groovy Collection API:*
@Test
void givenMapOfPerson_whenUsingCollectionMatching_thenShouldEvaluateMap() {
    assertTrue(personMap.keySet().any {it == "Regina"})
    assertFalse(personMap.keySet().every {it == "Albert"})
    assertFalse(personMap.values().every {it.age < 30})
    assertTrue(personMap.any {firstname, person -> firstname == "Abagail" && person.lastname == "Ballard"})
}
ご覧のとおり、Groovyは、マップを操作するときに_Stream_ APIを適切に置き換えるだけでなく、_java.util.Map#entrySet_メソッドを使用する代わりに、_Map_オブジェクトに対して直接チェックを実行することもできます。

4. コレクション内の1つ以上の要素を見つける

* 4.1。 リスト/セット*

述語を使用して要素を抽出することもできます。 使い慣れた_Stream_ APIアプローチから始めましょう。
@Test
void givenListOfPerson_whenUsingStreamFind_thenShouldReturnMatchingElements() {
    assertTrue(personList.stream().filter {it.age > 20}.findAny().isPresent())
    assertFalse(personList.stream().filter {it.age > 30}.findAny().isPresent())
    assertTrue(personList.stream().filter {it.age > 20}.findAll().size() == 3)
    assertTrue(personList.stream().filter {it.age > 30}.findAll().isEmpty())
}
ご覧のとおり、上記の例では、_Stream_ APIがそのアプローチを強制するため、単一の要素を見つけるために_java.util.Optional_を使用しています。
一方、Groovyははるかにコンパクトな構文を提供します。
@Test
void givenListOfPerson_whenUsingCollectionFind_thenShouldReturnMatchingElements() {
    assertNotNull(personList.find {it.age > 20})
    assertNull(personList.find {it.age > 30})
    assertTrue(personList.findAll {it.age > 20}.size() == 3)
    assertTrue(personList.findAll {it.age > 30}.isEmpty())
}
GroovyのAPIを使用することで、* _ St​​ream_の作成とフィルタリングをスキップできます*。

* 4.2。 Map*

__Mapの場合、___にはいくつかのオプションがあります。 *キー、値、または完全なエントリから要素を見つけることができます。*最初の2つは基本的に_List_または_Set_であるため、このセクションではエントリの検索の例を示します。
以前の_personMap_を再利用しましょう。
@Test
void givenMapOfPerson_whenUsingStreamFind_thenShouldReturnElements() {
    assertTrue(
      personMap.entrySet().stream()
        .filter {it.key == "Abagail" && it.value.lastname == "Ballard"}
        .findAny().isPresent())
    assertTrue(
      personMap.entrySet().stream()
        .filter {it.value.age > 20}
        .findAll().size() == 3)
}
また、単純化されたGroovyソリューション:
@Test
void givenMapOfPerson_whenUsingCollectionFind_thenShouldReturnElements() {
    assertNotNull(personMap.find {it.key == "Abagail" && it.value.lastname == "Ballard"})
    assertTrue(personMap.findAll {it.value.age > 20}.size() == 3)
}
この場合、メリットはさらに大きくなります。 __java.util.Map#entrySet __methodをスキップし、_Map_で提供される関数でクロージャーを使用します。

5. 結論

この記事では、Groovyが要素のチェックを簡素化し、いくつかのタイプのコレクションで要素を見つける方法を紹介しました。*
いつものように、このチュートリアルで使用される完全なコード例は、https://github.com/eugenp/tutorials/tree/master/core-groovy [GitHubで]から入手できます。