1. 概要

Groovy では、Javaと同じようにリストを操作できます。 ただし、拡張メソッドのサポートにより、かなり多くの機能が付属しています。

このチュートリアルでは、リストの変更、フィルタリング、および並べ替えに関するGroovyの見解を見ていきます。

2. Groovyリストの作成

Groovy provides certain interesting shortcuts when working with collections, which makes use of its support for dynamic typing and literal syntax.

省略構文を使用して、いくつかの値を含むリストを作成することから始めましょう。

def list = [1,2,3]

同様に、空のリストを作成できます。

def emptyList = []

By default, Groovy creates an instance of java.util.ArrayList.

However, we can also specify the type of list to create:

def linkedList = [1,2,3] as LinkedList
ArrayList arrList = [1,2,3]

次に、リストを使用して、コンストラクター引数を使用して他のリストを作成できます。

def copyList = new ArrayList(arrList)

We can also do this by cloning:

def cloneList = arrList.clone()

クローンを作成すると、リストの浅いコピーが作成されることに注意してください。

Groovy uses the “==” operator to compare the elements in two lists for equality.

Continuing with the previous example, on comparing cloneList with arrlist, the result is true:

assertTrue(cloneList == arrList)

Now let’s look at how to perform some common operations on lists.

3. Retrieving Items From a List

We can get an item from a list using the literal syntax:

def list = ["Hello", "World"]
assertTrue(list[1] == "World")

Or we can use the get() and getAt() methods:

assertTrue(list.get(1) == "World")
assertTrue(list.getAt(1) == "World")

We can also get items from a list using both positive and negative indices.

負のインデックスが使用されている場合、リストは右から左に読み取られます。

assertTrue(list[-1] == "World")
assertTrue(list.getAt(-2) == "Hello")

get()メソッドは負のインデックスをサポートしていないことに注意してください。

4. リストへのアイテムの追加

There are multiple shorthand ways for adding items to a list.

空のリストを定義し、それにいくつかの項目を追加しましょう。

def list = []

list << 1
list.add("Apple")
assertTrue(list == [1, "Apple"])

Next, we can also specify the index to place the item at.

Also, if the length of the list is less than the index specified, Groovy adds as many null values as the difference:

list[2] = "Box"
list[4] = true
assertTrue(list == [1, "Apple", "Box", null, true])

Lastly, we can use the “+=” operator to add new items to the list.

Compared to the other approaches, this operator creates a new list object and assigns it to the variable list:

def list2 = [1,2]
list += list2
list += 12        
assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])

5. リスト内のアイテムの更新

リテラル構文またはset()メソッドを使用して、リスト内のアイテムを更新できます。

def list =[1, "Apple", 80, "App"]
list[1] = "Box"
list.set(2,90)
assertTrue(list == [1, "Box", 90,  "App"])

In this example, the items at indexes 1 and 2 are updated with new values.

6. Removing Items From a List

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])

We can also remove an element by using the removeElement() method.

これにより、要素の最初の出現がリストから削除されます。

list.removeElement(5)
assertTrue(list == [1,2,3,5,6,6,7])

Additionally, we can use the minus operator to remove all occurrences of an element from the list.

This operator, however, does not mutate the underlying list — it returns a new list:

assertTrue(list - 6 == [1,2,3,5,7])

7. リストの反復

Groovy has added new methods to the existing Java Collections API.

These methods simplify operations such as filtering, searching, sorting, aggregating, etc. by encapsulating the boilerplate code. They also they support a wide range of inputs including closures and output data structures.

Let’s start by looking at the two methods for iterating over a list.

The each() method accepts a closure and is very similar to the foreach() method in Java.

Groovy passes an implicit parameter it that corresponds to the current element in each iteration:

def list = [1,"App",3,4]
list.each {println it * 2}

The other method, eachWithIndex(), provides the current index value in addition to the current element:

list.eachWithIndex{ it, i -> println "$i : $it" }

8. フィルタリング

フィルタリングはリストで頻繁に実行されるもう1つの操作であり、Groovyにはさまざまな方法が用意されています。

操作するリストを定義しましょう:

def filterList = [2,1,3,4,5,6,76]

To find the first object that matches a condition, we can use find:

assertTrue(filterList.find {it > 3} == 4)

To find all objects that match a condition, we can use findAll:

assertTrue(filterList.findAll {it > 3} == [4,5,6,76])

Let’s look at another example.

Here we want a list of all elements that are numbers:

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])

The difference between grep and find methods is that grep can accept an Object or a Closure as an argument.

So, it allows further reducing the condition statement to the bare minimum:

assertTrue(filterList.grep {it > 6} == [76])

さらに、 grep は、 Object#isCase(java.lang.Object)を使用して、リストの各要素の条件を評価します。

Sometimes, we may only be interested in the unique items in a list. There are two overloaded methods that we can use for this purpose.

The unique() method optionally accepts a closure and keeps in the underlying list only elements that match the closure conditions, while discarding others.

デフォルトでは自然な順序を使用して一意性を判断します。

def uniqueList = [1,3,3,4]
uniqueList.unique()
assertTrue(uniqueList == [1,3,4])

Alternatively, if the requirement is not to mutate the underlying list, we can use the toUnique() method:

assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique {it.size()} == ["A", "Ba", "Bat"])

リスト内の一部またはすべてのアイテムが特定の条件を満たすことを確認する場合は、 every()および any()メソッドを使用できます。

The every() method evaluates the condition in the closure against every element in the list.

Then it only returns true if all elements in the list satisfy the condition:

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 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])

Additionally, we can use the min() or max() methods to find the maximum or minimum value without explicitly calling sort():

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. 収集

Sometimes, we may want to modify the items in a list and return another list with updated values.

We can do this using the collect() method:

def list = ["Kay","Henry","Justin","Tom"]
assertTrue(list.collect{"Hi " + it} == ["Hi Kay","Hi Henry","Hi Justin","Hi Tom"])

11. 接合

At times, we may need to join the items in a list.

To do that, we can use the join() method:

assertTrue(["One","Two","Three"].join(",") == "One,Two,Three")

12. 結論

この記事では、GroovyがJava CollectionsAPIに追加する拡張機能のいくつかについて説明しました。

まず、文字通りの構文を確認し、次にリスト内の項目の作成、更新、削除、および取得におけるその使用法を確認しました。

最後に、リストの反復、フィルタリング、検索、収集、結合、および並べ替えに対するGroovyのサポートについて説明しました。

いつものように、この記事で説明されているすべての例は、GitHubから入手できます。