Groovy のリストの使い方

  1. 初期化
  2. 要素追加系
    1. 追加
      1. add メソッド
      2. << オペレータ、leftShift メソッド
      3. push メソッド
    2. 複数要素追加
      1. addAll メソッド
  3. 要素取得系
      1. list[index] (getAt)
    1. 先頭要素取得
      1. Object first()
      2. Object head()
    2. 最終要素取得
      1. Object last()
    3. 最大要素取得
      1. Object max()
      2. Object max(Closure closure)
    4. 最小要素取得
      1. Object min()
      2. Object min(Closure closure)
    5. pop
    6. 条件に一致する最初の要素を取得
      1. Object find()
      2. Object find(Closure closure)
    7. 条件に一致する要素を全部取得
      1. Collection findAll()
      2. Collection findAll(Closure closure)
      3. grep()
      4. grep(Object filter)
    8. Collection drop(int num)
    9. Collection dropRight(int num)
    10. Collection dropWhile(Closure closure)
    11. Collection take(int num)
    12. Collection takeRight(int num)
    13. Collection takeWhile(Closure closure)
  4. 値更新系
      1. list[index] = value (putAt)
      2. set メソッド
  5. 要素削除系
    1. 要素削除
      1. remove メソッド
      2. removeAt メソッド
      3. removeElement メソッド
    2. 全要素削除
      1. clear メソッド
  6. 要素数取得系
    1. int size() メソッド
    2. Number count(Object value) メソッド
    3. Number count(Closure closure) メソッド
    4. Map countBy(Closure closure) メソッド
  7. ループ系
    1. each
    2. eachWithIndex
    3. reverseEach メソッド
  8. 真偽判定系
    1. 真偽判定
    2. 条件に一致する要素が存在するか
      1. boolean any() メソッド
      2. boolean any(Closure closure) メソッド
    3. 全要素が条件に一致するか
      1. boolean every() メソッド
      2. boolean every(Closure closure) メソッド
    4. 一致する要素が存在するか
      1. boolean contains(Object o) メソッド
    5. 全要素が存在するか
      1. boolean containsAll(Collection<?> c) メソッド
      2. disjoint メソッド
  9. ソート
    1. Collection sort() メソッド
    2. Collection sort(Closure closure) メソッド
    3. Collection sort(Comparator comparator) メソッド
  10. 重複排除
    1. Collection unique() メソッド
    2. Collection unique(Closure closure) メソッド
    3. Collection unique(Comparator comparator) メソッド
  11. 分割したリストを作成
    1. split
  12. ソートしたリストを作成
    1. Collection toSorted()
    2. Collection toSorted(Closure closure)
    3. Collection toSorted(Comparator comparator)
  13. 重複排除したリストを作成
    1. Collection toUnique()
    2. Collection boolean unique(boolean mutate)
    3. Collection toUnique(Closure closure)
    4. Collection unique(boolean mutate, Closure closure)
  14. collect
      1. Collection collect()
      2. Collection collect(Closure transform)
      3. Collection collect(Collection collector, Closure transform)
      4. *.オペレータ
  15. グループ化
    1. Map groupBy(Closure closure)
    2. Map groupBy(List closures)
  16. inject
    1. Object inject(Closure closure)
    2. Object inject(Object initialValue, Closure closure)
  17. flatten
    1. Collection flatten()
  18. join
    1. String join(String separator)
  19. 集合処理系
    1. 和集合
      1. + オペレータ、plus(Iterable right) / plus(Object right) / plus(Collection right) メソッド
    2. 差集合
      1. - オペレータ、minus(Iterable removeMe) / minus(Object removeMe) / minus(Collection removeMe) メソッド
    3. 共通集合
      1. intersect メソッド
  20. その他のオペレータ系
      1. * オペレータ、multiply メソッド
      2. * オペレータ
      3. in オペレータ、isCase メソッド
      4. as オペレータ、asType メソッド
  21. その他

初期化

def emptyList = []
assert emptyList.size() == 0
assert emptyList instanceof ArrayList

def list = [1, 2, 3]
assert list.size() == 3
assert list.get(0) == 1
assert list.get(1) == 2
assert list.get(2) == 3

要素追加系

追加

add メソッド

def list = [1, 2, 3]
list.add(4)
assert list == [1, 2, 3, 4]

配列を add すると、配列のまま要素として追加される。

def list = [1, 2, 3]
list.add([4, 5])
assert list == [1, 2, 3, [4, 5]]

<< オペレータ、leftShift メソッド

def list = [1, 2, 3]
list << 4
assert list == [1, 2, 3, 4]

配列を << すると、配列のまま要素として追加される。

def list = [1, 2, 3]
list << [4, 5]
assert list == [1, 2, 3, [4, 5]]

<<はつなげられる。

def list = [1, 2, 3]
list << 4 << 5 << 6
assert list == [1, 2, 3, 4, 5, 6]

push メソッド

def list = [1, 2, 3]
list.push(0)
assert list == [0, 1, 2, 3]

複数要素追加

addAll メソッド

複数要素を追加する場合に利用する。

def list = [1, 2, 3]
list.addAll([4, 5])
assert list == [1, 2, 3, 4, 5]

要素取得系

list[index] (getAt)

def list = [1, 2, 3]
assert list[1] == 2

// 負数は末尾からのインデックス
assert list[-1] == 3

Range を指定することで、指定した範囲の要素をリストで取得できる。

def list = [1, 2, 3]
assert list[1..2] == [2, 3]

先頭要素取得

Object first()

def list = [1, 2, 3]
assert list.first() == 1

Object head()

def list = [1, 2, 3]
assert list.head() == 1

最終要素取得

Object last()

def list = [1, 2, 3]
assert list.last() == 3

最大要素取得

Object max()

def list = [1, 2, 3]
assert list.max() == 3

Object max(Closure closure)

def list = ['hello', 'hey', 'hi']
// クロージャの引数が1個の場合
assert list.max { it.length() } == 'hello'

// クロージャの引数が2個の場合
assert list.max { a, b -> a.length() <=> b.length() } == 'hello'

最小要素取得

Object min()

def list = [1, 2, 3]
assert list.min() == 1

Object min(Closure closure)

def list = ['hello', 'hey', 'hi']
// クロージャの引数が1個の場合
assert list.min { it.length() } == 'hi'

// クロージャの引数が2個の場合
assert list.min { a, b -> a.length() <=> b.length() } == 'hi'

pop

def list = [1, 2, 3]
assert list.pop() == 3
assert list == [1, 2]

条件に一致する最初の要素を取得

Object find()

def items = [null, 0, 0.0, false, '', [], 42, 43]
assert items.find() == 42

Object find(Closure closure)

def numbers = [1, 2, 3]
def result = numbers.find { it > 1}
assert result == 2

条件に一致する要素を全部取得

Collection findAll()

def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
assert items.findAll() == [1, 2, true, 'foo', [4, 5]]

Collection findAll(Closure closure)

def items = [0, 1, 2, 3, 4, 5]
def actual = items.findAll { it % 2 == 0 }
assert !actual.is(items) && actual == [0, 2, 4]

grep()

findAll()と同じ

def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
assert items.grep() == [1, 2, true, 'foo', [4, 5]]
assert items.grep() == items.findAll()

grep(Object filter)

def list = ['a', 'b', 'aa', 'bc', 3, 4.5]
assert list.grep( ~/a+/ )  == ['a', 'aa']
assert list.grep( ~/../ )  == ['aa', 'bc']
assert list.grep( Number ) == [ 3, 4.5 ]
assert list.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]

Collection drop(int num)

指定された要素数を除いたリストを返却

def strings = ['a', 'b', 'c']
def actual = strings.drop(2)
assert !strings.is(actual) && actual == ['c']

actual = strings.drop(0)
assert !strings.is(actual) && actual == ['a', 'b', 'c']
actual = strings.drop(5)
assert !strings.is(actual) && actual == []

Collection dropRight(int num)

def strings = ['a', 'b', 'c']
def actual = strings.dropRight(2)
assert !strings.is(actual) && actual == ['a']

actual = strings.dropRight(0)
assert !strings.is(actual) && actual == ['a', 'b', 'c']
actual = strings.dropRight(5)
assert !strings.is(actual) && actual == []

Collection dropWhile(Closure closure)

def strings = ['h', 'o', 'r', 's', 'e']
def actual = strings.dropWhile { it < 'r' }
assert !strings.is(actual) && actual == ['r', 's', 'e']

actual = strings.dropWhile { it <= 'r' }
assert !strings.is(actual) && actual == ['s', 'e']

Collection take(int num)

指定された要素数のリストを返却

def strings = ['a', 'b', 'c']
def actual = strings.take(2)
assert !strings.is(actual) && actual == ['a', 'b']

actual = strings.take(0)
assert !strings.is(actual) && actual == []
actual = strings.take(5)
assert !strings.is(actual) && actual == ['a', 'b', 'c']

Collection takeRight(int num)

def strings = ['a', 'b', 'c']
def actual = strings.takeRight(2)
assert !strings.is(actual) && actual == ['b', 'c']

actual = strings.takeRight(0)
assert !strings.is(actual) && actual == []
actual = strings.takeRight(5)
assert !strings.is(actual) && actual == ['a', 'b', 'c']

Collection takeWhile(Closure closure)

def strings = ['h', 'o', 'r', 's', 'e']
def actual = strings.takeWhile { it < 'r' }
assert !strings.is(actual) && actual == ['h', 'o']

actual = strings.takeWhile { it <= 'r' }
assert !strings.is(actual) && actual == ['h', 'o', 'r']

値更新系

list[index] = value (putAt)

def list = [1, 1, 3]
list[1] = 2
assert list == [1, 2, 3]

list[4] = 5
assert list == [1, 4, 3, null, 5]

範囲外のインデックスを指定した場合、自動拡張される。

def list = [1, 2, 3]
list[4] = 5
assert list == [1, 2, 3, null, 5]

Range を指定することで、指定した範囲の要素を更新できる。

def list = [1, 1, 1]
list[1..2] = [2, 3]
assert list == [1, 2, 3]

set メソッド

def list = [1, 1, 3]
list.set(1, 2)
assert list == [1, 2, 3]

範囲外のインデックスを指定した場合は、IndexOutOfBoundsException が発生する。

要素削除系

要素削除

remove メソッド

def list = ['a', 'b', 'c']
// 値を指定した場合
list.remove('b')
// 指定した値の要素が削除される
assert list == ['a', 'c']

list = ['a', 'b', 'c']
// 数値を指定した場合
list.remove(1)
// 指定したインデックスの要素が削除される
assert list == ['a', 'c']

List<Integer> の場合はインデックスも値も Integer で区別がつかないため、remove がインデックス指定でしか動かない。

def list = [1, 2, 3]
// List<Integer>の場合、必ずインデックス指定の削除になる
list.remove(1)
assert list == [1, 3]

そのため、要素の削除は後述の removeAt および removeElement を使った方が可読性が高まる。

removeAt メソッド

指定したインデックスの要素を削除する。

def list = [1, 2, 3]
list.removeAt(1)
assert list == [1, 3]

removeElement メソッド

指定した値の要素を削除する。

def list = [1, 2, 3]
list.removeElement(1)
assert list == [2, 3]

全要素削除

clear メソッド

def list = [1, 2, 3]
list.clear()
assert list == []

要素数取得系

int size() メソッド

def list = [1, 2, 3]
assert list.size() == 3

Number count(Object value) メソッド

指定した値の要素数を取得する。

def list = [1, 2, 3]
assert list.count(2) == 1

Number count(Closure closure) メソッド

クロージャで指定した条件に一致する要素数を取得する。

def list = [1, 2, 3]
assert list.count { it % 2 == 1 } == 2

Map countBy(Closure closure) メソッド

クロージャでグループ化する条件を指定し、その条件毎に一致する要素数を取得する。

def list = [1, 2, 3]
assert list.countBy { it % 2 } == [0: 1, 1: 2]

ループ系

each

def list = [1, 2, 3]
def actual = []
list.each {
    actucal << it
}
assert actual == [1, 2, 3]

eachWithIndex

def list = [1, 2, 3]
def actual = []
list.eachWithIndex { it, i ->
    actual << "${i}: ${it}"
}
assert actual == ['0: 1', '1: 2', '2: 3']

reverseEach メソッド

def list = [1, 2, 3]
def actual = []
list.reverseEach {
    actual << it
}
assert actual == [3, 2, 1]

真偽判定系

真偽判定

  • 空リストは false
assert ![]
  • 要素が有る場合は true
assert [0]
assert [null]

条件に一致する要素が存在するか

boolean any() メソッド

assert [false, true].any()
assert [0, 1].any()
assert ![0, 0].any()

boolean any(Closure closure) メソッド

assert [1, 2, 3].any { it == 2 }
assert ![1, 2, 3].any { it > 3 }

全要素が条件に一致するか

boolean every() メソッド

assert [true, true].every()
assert [1, 1].every()
assert ![1, 0].every()

boolean every(Closure closure) メソッド

def list = [3,4,5]
def greaterThanTwo = list.every { it > 2 }

一致する要素が存在するか

boolean contains(Object o) メソッド

assert [1, 2, 3].contains(1)

全要素が存在するか

boolean containsAll(Collection<?> c) メソッド

assert [1, 2, 3].containsAll([2, 3])

disjoint メソッド

共通集合がある場合は false、共通集合がない場合は true

assert [1, 2, 3].disjoint([4, 5, 6])

ソート

Collection sort() メソッド

def list = [3, 2, 1]
list.sort()
assert list == [1, 2, 3]

Collection sort(Closure closure) メソッド

ソート順をクロージャで指定してソートする。

def list = ['hello', 'hey', 'hi']
list.sort { it.length() }
assert list == ['hi', 'hey', 'hello']

Collection sort(Comparator comparator) メソッド

ソート順を Comparator で指定してソートする。

def list = ['hello', 'hey', 'hi']
list.sort { a, b -> a.length() <=> b.length() }
assert list == ['hi', 'hey', 'hello']

重複排除

Collection unique() メソッド

def letters = [1, 3, 3]
letters.unique()
assert letters == [1, 3]

Collection unique(Closure closure) メソッド

class Person {
    def fname
    def lname

    String toString() {
        return "${fname} ${lname}"
    }
}

def a = new Person(fname: 'John', lname: 'Taylor')
def b = new Person(fname: 'Clark', lname: 'Taylor')
def c = new Person(fname: 'Tom', lname: 'Cruz')
def d = new Person(fname: 'Clark', lname: 'Taylor')

def list = [a, b, c, d]
// クロージャの引数が1個の場合
list.unique { it.toString() }
assert list == [a, b, c]

list = [a, b, c, d]
// クロージャの引数が2個の場合
list.unique { x, y -> x.lname != y.lname ? x.lname <=> y.lname : x.fname <=> y.fname }
assert list == [a, b, c]

Collection unique(Comparator comparator) メソッド

class Person {
    def fname
    def lname

    String toString() {
        return "${fname} ${lname}"
    }
}

def a = new Person(fname: 'John', lname: 'Taylor')
def b = new Person(fname: 'Clark', lname: 'Taylor')
def c = new Person(fname: 'Tom', lname: 'Cruz')
def d = new Person(fname: 'Clark', lname: 'Taylor')

def list = [a, b, c, d]
list.unique({ x, y -> x.lname != y.lname ? x.lname <=> y.lname : x.fname <=> y.fname } as Comparator)
assert list == [a, b, c]

分割したリストを作成

split

def list = [1, 2, 3, 4]
list.split { it % 2 == 0} == [[2, 4], [1, 3]]

ソートしたリストを作成

Collection toSorted()

def list = [3, 4, 2, 5, 1]
def actual = list.toSorted()
assert !list.is(actual) && actual == [1, 2, 3, 4, 5]

Collection toSorted(Closure closure)

ソート順を指定する場合

def list = ['hello', 'hi', 'hey']
assert ['hi', 'hey', 'hello'] == list.toSorted { it.length() }

Collection toSorted(Comparator comparator)

ソート順を指定する場合

def list = ['hello', 'hi', 'hey']
assert ['hi', 'hey', 'hello'] == list.toSorted { a, b -> a.length() <=> b.length() }

重複排除したリストを作成

Collection toUnique()

def letters = ['c', 'a', 't', 's', 'a', 't', 'h', 'a', 't']
def expected = ['c', 'a', 't', 's', 'h']
assert letters.toUnique() == expected

Collection boolean unique(boolean mutate)

def letters = ['c', 'a', 't', 's', 'a', 't', 'h', 'a', 't']
def expected = ['c', 'a', 't', 's', 'h']
// 非破壊
def actual = letters.unique(false)
assert !actual.is(letters) && actual == expected
// 破壊
actual = letters.unique(true)
assert actual.is(letters) && letters == expected

Collection toUnique(Closure closure)

class Person {
    def fname
    def lname
    String toString() {
        return "${fname} ${lname}"
    }
}

def a = new Person(fname: 'John', lname: 'Taylor')
def b = new Person(fname: 'Clark', lname: 'Taylor')
def c = new Person(fname: 'Tom', lname: 'Cruz')
def d = new Person(fname: 'Clark', lname: 'Taylor')

def list = [a, b, c, d]
def list2 = list.toUnique { p1, p2 -> p1.lname != p2.lname ? p1.lname <=> p2.lname : p1.fname <=> p2.fname }
assert list2 == [a, b, c] && list == [a, b, c, d]
def list3 = list.toUnique { it.toString() }
assert list3 == [a, b, c] && list == [a, b, c, d]

Collection unique(boolean mutate, Closure closure)

class Person {
    def fname
    def lname
    String toString() {
        return "${fname} ${lname}"
    }
}

def a = new Person(fname: 'John', lname: 'Taylor')
def b = new Person(fname: 'Clark', lname: 'Taylor')
def c = new Person(fname: 'Tom', lname: 'Cruz')
def d = new Person(fname: 'Clark', lname: 'Taylor')

def list = [a, b, c, d]
// 非破壊
def actual = list.unique(false) { p1, p2 -> p1.lname != p2.lname ? p1.lname <=> p2.lname : p1.fname <=> p2.fname }
assert !actual.is(list) && actual == [a, b, c]
// 破壊
actual = list.unique(true) { p1, p2 -> p1.lname != p2.lname ? p1.lname <=> p2.lname : p1.fname <=> p2.fname }
assert actual.is(list) && list == [a, b, c]

collect

Collection collect()

assert [1, 2, 3].collect() == [1, 2, 3]

Collection collect(Closure transform)

assert [1, 2, 3].collect { it * 2 } == [2, 4, 6]
assert [1, 2, 3]*.multiply(2) == [2, 4, 6]

Collection collect(Collection collector, Closure transform)

def collector = [0]
def actual = [1, 2, 3].collect(collector) { it * 2 }
assert collector.is(actual) && actual == [0, 2, 4, 6]

*.オペレータ

collect(Closure transform)と同じ

class Car {
    String make
    String model
}
def cars = [
        new Car(make: 'Peugeot', model: '508'),
        new Car(make: 'Renault', model: 'Clio')]
assert cars*.make == ['Peugeot', 'Renault']
assert cars.collect { it?.make } == ['Peugeot', 'Renault']

cars = [
    new Car(make: 'Peugeot', model: '508'),
    null,
    new Car(make: 'Renault', model: 'Clio')]
assert cars*.make == ['Peugeot', null, 'Renault']
assert cars.collect { it?.make } == ['Peugeot', null, 'Renault']

assert null*.make == null
assert null?.collect { it?.make } == null

グループ化

Map groupBy(Closure closure)

def items = [0, 1, 2, 3, 4, 5, 6]
def actual = items.groupBy {it % 3 }
assert !actual.is(items) && actual == [0: [0, 3, 6], 1: [1, 4], 2: [2, 5]]

Map groupBy(List closures)

def items = [0, 1, 2, 3, 4, 5, 6]
def actual = items.groupBy([{ it % 2 }, { it % 3 }])
assert !items.is(actual) && actual == [0: [0: [0, 6], 1: [4], 2: [2]], 1: [0: [3], 1: [1], 2:[5]]]

inject

Object inject(Closure closure)

assert [ 1, 2, 3, 4 ].inject { acc, val ->  acc * val } == 1 * 2 * 3 * 4

assert [['a','b'], ['b','c'], ['d','b']].inject { acc, val -> acc.intersect( val ) } == ['a', 'b'].intersect(['b', 'c']).intersect(['d', 'b'])

def set = [ 't', 'i', 'm' ] as Set
assert set.inject { a, b -> a + b } == 't' + 'i' + 'm'

Object inject(Object initialValue, Closure closure)

def initialValue = [0]
[1, 2, 3, 4].inject(initialValue) { acc, val -> acc << val}
assert initialValue == [0, 1, 2, 3, 4]

assert [1, 2, 3, 4].inject(1) { acc, val -> acc * val } == 1 * 1 * 2 * 3 * 4

assert [1, 2, 3, 4].inject(0) { acc, val -> acc + val } == 0 + 1 + 2 + 3 + 4

assert ['quick', 'brown', 'fox'].inject('The') { acc, val -> acc + ' ' + val } == 'The quick brown fox'

assert ['rat', 'bat', 'cat'].inject('zzz') { min, next -> next < min ? next : min } == 'bat'

def max = { a, b -> [a, b].max() }
def animals = ['bat', 'rat', 'cat']
assert animals.inject('aaa', max) == 'rat'

flatten

Collection flatten()

assert [1, [2, 3], [[4]], [], 5].flatten() == [1, 2, 3, 4, 5]

join

String join(String separator)

assert [1, 2, 3].join(', ') == '1, 2, 3'

集合処理系

和集合

+ オペレータ、plus(Iterable right) / plus(Object right) / plus(Collection right) メソッド

def list = [1, 2]
assert list.plus([3, 4]) == [1, 2, 3, 4]
assert list + [3, 4] == [1, 2, 3, 4]
assert list.plus(3) == [1, 2, 3]
assert list + 3 == [1, 2, 3]

差集合

- オペレータ、minus(Iterable removeMe) / minus(Object removeMe) / minus(Collection removeMe) メソッド

def list = [1, "a", true, true, false, 5.3]
assert list.minus([true, 5.3]) == [1, "a", false]
assert list - [true, 5.3] == [1, "a", false]
list = ["a", 5, 5, true]
assert list.minus(5) == ["a", true]
assert list - 5 == ["a", true]
list = [1, 2, 3, 4, 3, 2, 1]
def actual = list
actual -= 3
assert !actual.is(list) && actual == [1, 2, 4, 2, 1]

共通集合

intersect メソッド

assert [1, 2, 3].intersect([3, 4, 5]) == [3]

その他のオペレータ系

* オペレータ、multiply メソッド

assert [1, 2, 3] * 2 == [1, 2, 3, 1, 2, 3]

* オペレータ

def list = [1, 2, 3]
int function(int x, int y, int z) {
    x * y + z
}

def args = [4, 5, 6]

assert function(*args) == function(4, 5, 6)

args = [4]
assert function(*args, 5, 6) == function(4, 5, 6)

def items = [4, 5]
assert [1, 2, 3, *items, 6] == [1, 2, 3, 4, 5, 6]

in オペレータ、isCase メソッド

def list = ['Grace', 'Rob', 'Emmy']
assert list in ArrayList
assert ArrayList.isCase(list)

assert 'Emmy' in list
switch ('Emmy') {
    case list:
        assert true
        break
    default:
        assert false
}
assert list.isCase('Emmy')

as オペレータ、asType メソッド

指定された型に変換する。

def list = [1, 2, 3]
assert (list as HashSet) in HashSet
assert list.asType(HashSet) in HashSet

その他

  • indexOf
  • lastIndexOf
  • sum

コメント