Groovy

「GroovyはJavaの拡張ライブラリといえる」(テストコードで利用)

http://groovy.codehaus.org/groovy-jdk/

★Javaと違ったところ

if文では、「0やnullはfalse、それ以外はtrue」と判断

セミコロン、returnキーワードは省略可

thisキーワードはstaticメソッドの中でも使える(クラス自身を指す)

メソッドとクラスはデフォルトでpublic

protected はJavaにおけるpackage-protectedとprotectedの両方に相当

チェック例外と非チェック例外の区別がない

未定義のメンバを使ったり、間違った型の引数を渡したりしてもJavaのようにコンパイルエラーが起こらない

★Javaにはないところ

クロージャ

リストやマップのためのネイティブ構文

GroovyMarkupおよびGPathのサポート

正規表現のネイティブサポート

ポリモルフィックな イテレーション(繰り返し)と強力な switch文

動的および静的型付けのサポート(メソッド、フィールド、変数の型宣言は省略可)

文字列の中に式を埋め込むこと

JDKに追加された新しいヘルパーメソッド

Beansのプロパティやイベントリスナの追加を書くためのよりシンプルな構文

?.演算子を使った安全なナビゲーション

★デフォルトのimport

java.io.*

java.lang.*

java.math.BigDecimal

java.math.BigInteger

java.net.*

java.util.*

groovy.lang.*

groovy.util.*

★基本

Groovy Java

等値性 a == b a.equals(b)

同一性 a.is(b) a == b

print 'Hello, Groovy!' // 改行なし

println 'Hello, Groovy!' // 改行あり

printf 'Hello, %s', 'Groovy!' // 整形

for文

for (int i =0; i < len; i++)

for (i in 0..len-1)

for (i in 0..<len)

for ( i in [0, 1, 2, 3, 4] )

for ( i in (0..4).toArray() )

def map = ['a':1, 'b':2, 'c':3]

x = 0

for ( e in map ) {

x += e.value

}

assert x == 6

或いは

x = 0

for ( v in map.values() ) {

x += v

}

assert x == 6

def text = "abc"

def list = []

for (c in text) {

list.add(c)

}

assert list == ["a", "b", "c"]

switch文

def x = 1.23

def result = ""

switch ( x ) {

case "foo":

result = "found"

break

case [4, 5, 6, 'inList']:

result = "list"

break

case 12..30:

result = "range"

break

case Integer:

result = "integer"

break

case Number:

result = "number"

break

default:

result = "default"

}

assert result == "number"

★オープンクラス

obj = new Expando()

obj.name = "Andy"

obj.message = "Hello"

obj.say = {

name = it

println message + name

}

obj.say("Robby")

★文字列

def msg = "Hello"

msg -= "l"

msg *= 3

println msg //HeloHeloHelo

def text = "nice!"

def x = text[2]

assert x == "c"

assert x.class == String

def sub = text[1..3]

assert sub == 'ice'

def x = text[-1]

assert x == "!"

def name = text[3..1]

assert name == "eci"

★Closure

msg = { println "Hello ${it}!" }

或いは

msg = {str -> println "Hello ${str}!" }

msg('Andy')

total = 0

(1..100).each { total += it }

或いは

total = 0

n = 1

(100).times { total += n++ }

def add = { x, y -> x + y }

def mult = { x, y -> x * y }

def min = { x, y -> [x,y].min() }

def max = { x, y -> [x,y].max() }

def do(list, Closure invoke) {

if (list.size() < 2) return []

def next = invoke(list[0], list[1])

return [next] + pairWise(list[1..-1], invoke)

}

assert do(1..5, add) == [3,5,7,9]

assert do(1..5, mult) == [2,6,12,20]

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

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

assert 'dcba-abcd' == ['a','b','c','d'].inject('-'){

result, item -> item + result + item }

assert [1,2,3].grep{ it < 3 } == [1,2]

assert [1,2,3].any{ it % 2 == 0 }

assert [1,2,3].every{ it < 4 }

assert (1..4).collect{ it * 2 }.join() == '2468'

def numbers = [ 5, 7, 9, 12 ]

assert numbers.findAll { it in 6..10 } == [7,9]

numbers.eachWithIndex{ num, idx -> println "$idx: $num" }

def words = ['ant', 'buffalo', 'cat', 'dinosaur']

assert words.findAll{ w -> w.size() > 4 } == ['buffalo', 'dinosaur']

assert words.collect{ it[0] } == ['a', 'b', 'c', 'd']

map.each() { key, value -> println "${key} == ${value}" };

list.eachWithIndex() { obj, i -> println " ${i}: ${obj}" }; // 0: xxx

map.eachWithIndex() { obj, i -> println " ${i}: ${obj}" }; // 0: key=value

fpath = ".\\sample.txt"

file = new File(fpath)

line = 0

file.eachLine { println (++line + ": " + it) }

fpath = ".\\fold"

file = new File(fpath)

file.eachFile { println (it) }

★GroovyCollections Utility Class

def classes = ['A', 'B']

def methods = ['min', 'max', 'sum']

def combinations = GroovyCollections.combinations([classes, methods])

assert 2 * 3 == combinations.size()

assert [['A', 'min'], ['B', 'min'], ['A', 'max'], ['B', 'max'], ['A', 'sum'], ['B', 'sum']] == combinations

assert 3 == combinations.findAll { it[0] == 'A' }.size()

def keys = ['username', 'email']

def values = ['Andy', 'xxx@gmail.com', 'not-tranposed']

def transpose = GroovyCollections.transpose([keys, values, [0, 1]])

assert 2 == transpose.size()

assert [['username', 'Andy', 0], ['email', 'xxx@gmail.com', 1]] == transpose

★List

assert [].size() == 0

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

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

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

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

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

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

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

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

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

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

assert [1,2,3].collect{ it + 3 } == [4,5,6]

assert [1,2,3,1].unique().size() == 3 //uniqueは直接に上書き

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

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

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

assert [1,2,3,4].sum() == 10

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

assert [4,2,1,3].findAll{ it % 2 == 0 } == [4,2]

def animals = ['cat', 'kangaroo', 'koala', 'dog']

def kanimals = animals[1..2]

assert animals.findAll{ it =~ /k.*/ } == kanimals

assert animals.find{ it =~ /k.*/ } == kanimals[0]

assert animals.grep(~/k.*/) == kanimals

assert [[1, 2, 3, 4], ['a', 'b', 'c', 'd']].transpose()

== [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']]

assert [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']].flatten()

== [1, 'a', 2, 'b', 3, 'c', 4, 'd']

def list = ['a', 'b', 'c', 'd']

list[1..1] = ['1', '2']

assert list == ['a', '1', '2', 'c', 'd']

def list = ['a', 'b', 'c', 'd', 'e']

list[1..3] = ['1', '2', '3']

assert list == ['a', '1', '2', '3', 'e']

def list = ['a', 'b', 'c']

list[1] = ['1', '2']

assert list == ['a', ['1', '2'], 'c']

def list = ['a', 'b', 'c', 'd', 'e']

list[1..3] = ['1', '2']

assert list == ['a', '1', '2', 'e']

def list = [1, 2, 3, 5, 7, 8]

assert list.groupBy{ it % 2 } == [1:[1, 3, 5, 7], 0:[2, 8]]

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

def list = [5, 6, 7, 8]

assert list.get(2) == 7

assert list[2] == 7

assert list instanceof java.util.List

def list = 100..200

def sub = list[1, 3, 20..25, 33]

assert sub == [101, 103, 120, 121, 122, 123, 124, 125, 133]

assert [1, 3, 5] == ['a', 'bbb', 'ccccc']*.size()

def list = ['a','b','c','d']

def newList = []

list.collect( newList ) {

it.toUpperCase()

}

或いは

def clos = { it.toUpperCase() }

list.collect( newList, clos )

★Map

assert [:].size() == 0

def map = [a:1, b:2, c:3]

assert map instanceof java.util.HashMap

assert map.size() == 3

assert map['a'] == 1

assert map.a == 1

assert map.get('a') == 1

assert map.get('d') == null

assert map.get('d', 0) == 0 // デフォルト値を設定

assert map.d == 0 // 設定された後なので

map['e'] = 1

assert map.e == 1

def key = 'a'

assert ['x':1] == [x:1]

assert ['a':1] == [(key):1]

assert ['c':100, *:['a':11, 'aa':22, 'aaa':33]]

== ['c':100, 'a':11, 'aa':22, 'aaa':33]

★Range

assert 1..10 == new IntRange(1, 10)

assert 1..<5 == 1..4

assert -2..<2 == -2..1

assert 2..<-2 == 2..-1

assert (1..10).size() == 10

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

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

assert ('A'..'E').step(2) == ['A', 'C', 'E']

assert (3..1).isReverse()

assert !(1..3).isReverse()

assert (1..2).contains(1)

assert !(1..2).contains(3)

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

def range = 5..8

assert range.from == 5

assert range.to == 8

assert range.reverse() == 8..5

assert range.size() == 4

assert range.get(2) == 7

assert range[2] == 7

assert range instanceof java.util.List

def range = 'a'..'d'

assert range.size() == 4

assert range.get(2) == 'c'

assert range[2] == 'c'

assert range instanceof java.util.List

assert range.contains('d')

assert ! range.contains('e')

★Inject Method

def total = 0

(1..4).each { total += it }

assert 10 == total

あるいは

def total = (1..4).inject(0) { result, i -> result + i }

assert 10 == total

def list = [1,2,3]

result = list.inject(0){s, l -> s += l }

assert 6 == result

def list = ['like','sports']

result = list.inject('I'){s, l -> "$s $l" }

assert "I like sports" == result

def a = [1, 2, 3]

def b = [4, 5, 6]

def m = [a, b].transpose().inject([:]) { s, l -> s + [(l[0]): l[1]] }

assert m == [1: 4, 2: 5, 3: 6]

サンプル1

class Person {

String username

String email

}

def persons = [

new Person(username:'Andy', email: 'xxx@gmail.com'),

new Person(username:'Tom', email: 'yyy@gmail.com')

]

// An empty map as the starting point for the result

def map = persons.inject([:]) { result, person ->

result[person.username] = person.email

result

}

assert [Andy: 'xxx@gmail.com', Tom: 'yyy@gmail.com'] == map

サンプル2

Java版

abstract class A {

public int getTotal(int[] values) {

int total = 10;

for (int value : values) {

total += strategy(value);

}

return total;

}

protected abstract int strategy(int value);

}

class B extends A {

protected int strategy(int value) {

return value / 2;

}

}

class C extends A {

protected int strategy(int value) {

return value * 2;

}

}

assertEquals(new B().getTotal(new int[]{0, 1, 2}), 10 + 1/2 + 1);

assertEquals(new C().getTotal(new int[]{0, 1, 2}), 10 + 2 + 4);

Groovy版

Closure a = { values, check -> values.inject(10){x, y -> x + check(y)} }

Closure b = { a(it) {it / 2} }

Closure c = { a(it) {it * 2} }

assert b([0, 1, 2]) == 10 + 1/2 + 1

assert c([0, 1, 2]) == 10 + 2 + 4