Groovyのリスト

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

  • Groovy

1. 概要

link:/groovy-language[Groovy]では、https://www.baeldung.com/java-collections [Java]で行うようにリストを操作できます。 ただし、拡張メソッドのサポートにより、かなり多くの機能が搭載されています。
このチュートリアルでは、リストの変更、フィルタリング、ソートに関するGroovyの見解を見ていきます。

2. Groovyリストを作成する

Groovyは、動的タイピングとリテラル構文のサポートを利用するコレクションを操作するときに、特定の興味深いショートカットを提供します。
簡単な構文を使用して、いくつかの値を持つリストを作成することから始めましょう。
def list = [1,2,3]
同様に、空のリストを作成できます。
def emptyList = []
デフォルトでは、Groovyは_java.util.ArrayList._のインスタンスを作成しますが、*作成するリストのタイプを指定することもできます*:
def linkedList = [1,2,3] as LinkedList
ArrayList arrList = [1,2,3]
次に、リストを使用して、コンストラクター引数を使用して他のリストを作成できます。
def copyList = new ArrayList(arrList)
またはクローニングによって:
def cloneList = arrList.clone()
クローンを作成すると、リストの浅いコピーが作成されることに注意してください。
Groovyは、「==」演算子を使用して、2つのリストの要素が等しいかどうかを比較します。 前の例を続けて、_cloneList_を_arrlist_と比較すると、結果は_true:_です。
assertTrue(cloneList == arrList)
次に、リストで一般的な操作を実行する方法を見てみましょう。

[[Get Items from List]]
=== 3. リストからアイテムを取得する

次のようなリテラル構文を使用して、リストからアイテムを取得できます。
def list = ["Hello", "World"]
assertTrue(list[1] == "World")
または_get()_および_getAt()_メソッドを使用します。
assertTrue(list.get(1) == "World")
assertTrue(list.getAt(1) == "World")
正と負の両方のインデックスを使用して、リストからアイテムを取得することもできます。 負のインデックスが使用される場合、リストは右から左に読み取られます。
assertTrue(list[-1] == "World")
assertTrue(list.getAt(-2) == "Hello")
_get()_メソッドは負のインデックスをサポートしないことに注意してください。

[[Add Items to List]]
=== 4. リストへのアイテムの追加

リストにアイテムを追加するための複数の速記方法があります。 空のリストを定義して、いくつかのアイテムを追加しましょう。
def list = []

list << 1
list.add("Apple")
assertTrue(list == [1, "Apple"])
次に、アイテムを配置するインデックスを指定することもできます。 また、*リストの長さが指定されたインデックスより短い場合、Groovyは差と同じ数の_null_値を追加します*:
list[2] = "Box"
list[4] = true
assertTrue(list == [1, "Apple", "Box", null, true])
最後に、“ _ + =” _演算子を使用して、新しいアイテムをリストに追加できます。 他のアプローチと比較して、*この演算子は新しいリストオブジェクトを作成し、変数_list _:*に割り当てます
def list2 = [1,2]
list += list2
list += 12
assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])

[[Update Items in a List]]
=== 5. リスト内のアイテムを更新する

リテラル構文または_set()_メソッドを使用して、リスト内のアイテムを更新できます。
def list =[1, "Apple", 80, "App"]
list[1] = "Box"
list.set(2,90)
assertTrue(list == [1, "Box", 90,  "App"])
この例では、インデックス1と2のアイテムが新しい値で更新されます。

[[Remove Items from List]]
=== 6. リストからアイテムを削除する

_remove()_メソッドを使用して、特定のインデックスのアイテムを削除できます。
def list = [1,2,3,4,5,5,6,6,7]
list.remove(3)
assertTrue(list == [1,2,3,5,5,6,6,7])
または、_removeElement()_メソッドを使用して要素を削除することもできます。 これにより、リストから最初に出現した要素が削除されます。
list.removeElement(5)
assertTrue(list == [1,2,3,5,6,6,7])
さらに、* _ minus_演算子を使用して、リストから要素のすべての出現を削除できます*。 ただし、この演算子は基になるリストを変更しません。新しいリストを返します。
assertTrue(list - 6 == [1,2,3,5,7])

[[Iterating on a List]]
=== 7. リストの繰り返し

Groovyは、既存のJava _Collections_ APIに新しいメソッドを追加しました。 これらのメソッドは、定型コードをカプセル化することにより、フィルタリング、検索、ソート、集約などの操作を簡素化します。 また、クロージャーや出力データ構造を含む幅広い入力をサポートします。
リストを反復処理する2つの方法を見てみましょう。
_each()_メソッドはクロージャを受け入れ、Javaの_foreach_()メソッドに非常に似ています。 Groovyは、各反復の現在の要素に対応する暗黙的なパラメーター_it_を渡します。
def list = [1,"App",3,4]
list.each {println it * 2}
他のメソッド_eachWithIndex()_は、現在の要素に加えて現在のインデックス値を提供します。
list.eachWithIndex{ it, i -> println "$i : $it" }

8. フィルタリング

フィルタリングはリストで頻繁に実行される別の操作であり、Groovyはさまざまな方法から選択できます。
操作するリストを定義しましょう:
def filterList = [2,1,3,4,5,6,76]
条件に一致する最初のオブジェクトを見つけるには、_find_を使用できます。
assertTrue(filterList.find {it > 3} == 4)
条件に一致するすべてのオブジェクトを検索するには、_findAll_を使用できます。
assertTrue(filterList.findAll {it > 3} == [4,5,6,76])
別の例を見てみましょう。 ここでは、数字であるすべての要素のリストが必要です。
assertTrue(filterList.findAll {it instanceof Number} == [2,1,3,4,5,6,76])
または、_grep_メソッドを使用して同じことを行うこともできます。
assertTrue(filterList.grep( Number ) == [2,1,3,4,5,6,76])
  • _grep_メソッドと_find_メソッドの違いは、_grep_が_Object_または_Closure_を引数として受け入れることができることです*。したがって、条件ステートメントをさらに最小限に抑えることができます。

assertTrue(filterList.grep {it > 6} == [76])
さらに、_grep_は_Object#isCase(java.lang.Object)_を使用して、リストの各要素の条件を評価します。
時々*リスト内のユニークなアイテムにのみ興味があるかもしれません*。 この目的に使用できるオーバーロードメソッドは2つあります。
_unique()_メソッドは、オプションでクロージャーを受け入れ、クロージャーの条件に一致する要素のみを基になるリストに保持し、その他は破棄します。 デフォルトで自然順序付けを使用して、一意性を決定します。
def uniqueList = [1,3,3,4]
uniqueList.unique()
assertTrue(uniqueList == [1,3,4])
あるいは、基になるリストを変更する必要がない場合は、_toUnique()_メソッドを使用できます。
assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique {it.size()} == ["A", "Ba", "Bat"])
*リスト内の一部またはすべてのアイテムが特定の条件を満たすことを確認する場合は、_every()_および_any()_メソッドを使用できます。*
_every()_メソッドは、リスト内のすべての要素に対してクロージャー内の条件を評価します。 次に、リスト内のすべての要素が条件を満たす場合にのみ_true_を返します。
def conditionList = [2,1,3,4,5,6,76]
assertFalse(conditionList.every {it < 6})
一方、_any()_メソッドは、リスト内のいずれかの要素が条件を満たしている場合、_true_を返します。
assertTrue(conditionList.any {it % 2 == 0})

9. ソート

デフォルトでは、Groovyは自然順序付けに基づいてリスト内のアイテムをソートします。
assertTrue([1,2,1,0].sort() == [0,1,1,2])
しかし*カスタムソートロジックで_Comparator_を渡すこともできます*:
Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1}
def list = [1,2,1,0]
list.sort(mc)
assertTrue(list == [2,1,1,0])
さらに、_sort():_を明示的に呼び出すことなく、_min()_または_max()_メソッドを使用して最大値または最小値を見つけることができます。
def strList = ["na", "ppp", "as"]
assertTrue(strList.max() == "ppp")
Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1}
def numberList = [3, 2, 0, 7]
assertTrue(numberList.min(minc) == 0)

10. 収集

リスト内のアイテムを変更し、更新された値を含む別のリストを返したい場合があります。 これは、_collect()_メソッドを使用して実行できます。
def list = ["Kay","Henry","Justin","Tom"]
assertTrue(list.collect{"Hi " + it} == ["Hi Kay","Hi Henry","Hi Justin","Hi Tom"])

11. 接合

場合によっては、リスト内のアイテムを結合する必要があります。 これを行うには、_join()_メソッドを使用できます。
assertTrue(["One","Two","Three"].join(",") == "One,Two,Three")

12. 結論

この記事では、GroovyがJava _Collections_ APIに追加するいくつかの拡張機能について説明しました。
まず、リテラル構文を見てから、リスト内のアイテムを作成、更新、削除、取得する際の使用法を確認しました。
最後に、リストの反復、フィルタリング、検索、収集、結合、および並べ替えに対するGroovyのサポートを確認しました。
いつものように、記事で説明されているすべての例はhttps://github.com/eugenp/tutorials/tree/master/core-groovy[over on GitHub]で入手できます。