web-dev-qa-db-ja.com

Groovyの隠された機能?

このスレッドではGroovyが忘れられたようですので、Groovyについても同じ質問をします。

  • Groovyコアへの回答を制限してみてください
  • 回答ごとに1つの機能
  • ドキュメントへのリンクだけでなく、機能の例と簡単な説明を提供します
  • 最初の行として太字のタイトルを使用して機能にラベルを付けます

参照:

  1. Pythonの隠された機能
  2. Rubyの隠された機能
  3. Perlの隠された機能
  4. Javaの隠された機能
78
anon

スプレッドドット演算子を使用

_def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]
_

これはanimals.collect { it.size() }のショートカットです。

56
Paul King

withメソッドを使用すると、次のようになります。

 myObj1.setValue(10)
 otherObj.setTitle(myObj1.getName())
 myObj1.setMode(Obj1.MODE_NORMAL)

これに

 myObj1.with {
    value = 10
    otherObj.title = name
    mode = MODE_NORMAL
 }
39
Rui Vieira

誰もが知っているエルビス

def d = "hello";
def obj = null;

def obj2 = obj ?: d;   // sets obj2 to default
obj = "world"

def obj3 = obj ?: d;  // sets obj3 to obj (since it's non-null)
37
billjamesdev

疑似オブジェクトとしてハッシュを使用する。

def x = [foo:1, bar:{-> println "Hello, world!"}]
x.foo
x.bar()

ダックタイピングと組み合わせると、このアプローチで大いに役立つことができます。 「as」演算子を削除する必要はありません。

37
Robert Fischer

オブジェクトにあるメソッドを見つけるのは、metaClassに尋ねるのと同じくらい簡単です。

"foo".metaClass.methods.name.sort().unique()

プリント:

["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo",
 "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", 
 "endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars", 
 "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", 
 "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", 
 "replaceAll", "replaceFirst", "split", "startsWith", "subSequence", "substring", 
 "toCharArray", "toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]
35
Ted Naleid

欠落している静的メソッドをインターセプトするには、以下を使用します

 Foo {
    static A() { println "I'm A"}

     static $static_methodMissing(String name, args) {
        println "Missing static $name"
     }
 }

Foo.A()  //prints "I'm A"
Foo.B()  //prints "Missing static B"

-ケン

28
ken

破壊

Groovyでは別の名前で呼ばれることもあります。それはclojureでの破壊と呼ばれます。あなたはそれがどれほど便利になるか信じられないでしょう。

def list = [1, 'bla', false]
def (num, str, bool) = list
assert num == 1
assert str == 'bla'
assert !bool
24
Bojan Dolinar

Java groovyを使用したコードをテストする場合、オブジェクトグラフビルダーは素晴らしいです:

def company = builder.company( name: 'ACME' ) {
   address( id: 'a1', line1: '123 Groovy Rd', Zip: 12345, state: 'JV' )
   employee(  name: 'Duke', employeeId: 1 ){
      address( refId: 'a1' )
   }
}

標準機能ですが、それでも本当に素晴らしいです。

ObjectGraphBuilder

(ビルダーサポートを機能させるには、POJOのプロパティをListではなくnullsのデフォルト値にする必要があります。)

21
krosenvold
println 
"""
Groovy has "multi-line" strings.
Hooray!
"""
19

Groovy 1.6では、正規表現はすべてのクロージャーイテレーター(それぞれ、収集、挿入など)で機能し、キャプチャグループを簡単に操作できます。

def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""

assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> 
        "$file -> $path"
    } ==  ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
15
Ted Naleid

宇宙船オペレーターの使用

私は 宇宙船演算子 が好きで、あらゆる種類のカスタムソートシナリオに役立ちます。使用例のいくつかは ここ です。特に役立つ状況の1つは、複数のフィールドを使用してオブジェクトのオンザフライでコンパレータを作成することです。例えば.

def list = [
    [ id:0, first: 'Michael', last: 'Smith', age: 23 ],
    [ id:1, first: 'John', last: 'Smith', age: 30 ],
    [ id:2, first: 'Michael', last: 'Smith', age: 15 ],    
    [ id:3, first: 'Michael', last: 'Jones', age: 15 ],   
]

// sort list by last name, then first name, then by descending age
assert (list.sort { a,b -> a.last <=> b.last ?: a.first <=> b.first ?: b.age <=> a.age })*.id == [ 3,1,0,2 ]
15
mmigdol

Javaとは異なり、Groovyでは、プリミティブ型だけでなく、switchステートメントで何でも使用できます。典型的なeventPerformedメソッド

switch(event.source) {
   case object1:
        // do something
        break
   case object2:
        // do something
        break
}
15
Rui Vieira

閉鎖により、リソース管理の古い試行錯誤のゲームがすべてなくなる可能性があります。ファイルストリームは、ブロックの最後で自動的に閉じられます。

new File("/etc/profile").withReader { r ->
    System.out << r
}
14

GDK内の変換によって提供される機能groovy.transformパッケージなど:

  • @Immutable :@ Immutableアノテーションは、コンパイラにAST変換を実行するように指示します。これにより、必要なゲッター、コンストラクター、equals、hashCode、および不変クラスの作成時に通常記述されるその他のヘルパーメソッドが追加されます。定義されたプロパティを使用します。
  • @CompileStatic :これにより、GroovyコンパイラーはJavaのスタイルでコンパイル時チェックを使用し、静的コンパイルを実行して、Groovyメタオブジェクトプロトコルをバイパスします。
  • @Canonical :@ Canonicalアノテーションは、コンパイラーにAST変換を実行するように指示します。これにより、位置コンストラクター、equals、hashCode、およびプリティプリントtoStringがクラスに追加されます。

その他:

  • @Slf4j このローカル変換は、LogBackロギングを使用してプログラムにロギング機能を追加します。 logという名前のバインドされていない変数に対するすべてのメソッド呼び出しは、ロガーへの呼び出しにマップされます。
  • GroovyのXML Slurper :XMLの簡単な解析。キラー機能!
13
Hans Westerbeek

ToSpreadMap()を使用してリストをマップに変換できます。これは、リスト内の順序がキーとそれに関連付けられた値を決定するのに十分な場合に便利です。以下の例を参照してください。

def list = ['key', 'value', 'foo', 'bar'] as Object[]
def map = list.toSpreadMap()

assert 2 == map.size()
assert 'value' == map.key
assert 'bar' == map['foo']
12
ken

クロージャーベースのインターフェースの実装

次のような型指定された参照がある場合:

MyInterface foo

以下を使用して、インターフェース全体を実装できます。

foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface

または、各メソッドを個別に実装する場合は、次を使用できます。

foo = [bar: {-> println "bar invoked"}, 
    baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
12
Dónal

リストからnull値を削除します

def list = [obj1, obj2, null, obj4, null, obj6]
list -= null
assert list == [obj1, obj2, obj4, obj6]
8
BIdesi

@ Delegate

class Foo {
    def footest() { return "footest"}   
}

class Bar {
    @Delegate Foo foo = new Foo()     
}

def bar = new Bar()

assert "footest" == bar.footest()
7
Omnipresent

私は少し遅れていることを知っていますが、ここにはいくつかの素晴らしい機能が欠けていると思います:

コレクションのプラス/マイナス演算子

def l = [1, 2, 3] + [4, 5, 6] - [2, 5] - 3 + (7..9)
assert l == [1, 4, 6, 7, 8, 9]

def m = [a: 1, b: 2] + [c: 3] - [a: 1]
assert m == [b: 2, c: 3]

switchステートメント

switch (42) {
  case 0: .. break
  case 1..9: .. break
  case Float: .. break
  case { it % 4 == 0 }: .. break
  case ~/\d+/: .. break
}

範囲とインデックス付け

assert (1..10).step(2) == [1, 3, 5, 7, 9]
assert (1..10)[1, 4..8] == [2, 5, 6, 7, 8, 9]
assert ('a'..'g')[-4..-2] == ['d', 'e', 'f']

nicode変数名

def α = 123
def β = 456
def Ω = α * β
assert Ω == 56088
7
micha

リテラルのアンダースコア

長いリテラルの数字を書くとき、たとえば数千の単語のグループなど、いくつかの数字がどのようにグループ化されているかを理解するのは難しいです。数字のリテラルにアンダースコアを配置できるようにすることで、それらのグループを簡単に見つけることができます。

long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
double monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010
6
Pankaj Shinde

暗黙の引数を使用した引数の並べ替えも、もう1つの優れた方法です。

このコード:

def foo(Map m=[:], String msg, int val, Closure c={}) {
  [...]
}

これらすべての異なるメソッドを作成します。

foo("msg", 2, x:1, y:2)
foo(x:1, y:2, "blah", 2)
foo("blah", x:1, 2, y:2) { [...] }
foo("blah", 2) { [...] }

もっと。名前付き引数と序数引数を間違った順序/位置に配置して失敗することは不可能です。

もちろん、「foo」の定義では、「Stringmsg」と「intval」から「String」と「int」を省略できます。わかりやすくするために省略しました。

5
Robert Fischer

メソッドパラメータでspread演算子を使用

これは、コードをデータに変換するときに非常に役立ちます。

def exec(operand1,operand2,Closure op) {
    op.call(operand1,operand2)
}

def addition = {a,b->a+b}
def multiplication = {a,b->a*b}

def instructions = [
     [1,2,addition],
     [2,2,multiplication]
]

instructions.each{instr->
    println exec(*instr)
}

この使用法も役立ちます:

String locale="en_GB"

//this invokes new Locale('en','GB')
def enGB=new Locale(*locale.split('_'))
4
Luis Muñiz

パラメータとしてのクロージャとparameter-default-valuesの組み合わせだと思います。

public void buyItems(Collection list, Closure except={it > 0}){
  list.findAll(){except(it)}.each(){print it}
}
buyItems([1,2,3]){it > 2}
buyItems([0,1,2])

プリント:「312」

4
Peter Rader

メモ化

メモ化は、コストのかかる関数呼び出しの結果を保存し、同じ引数を使用して関数が再度呼び出されるたびにキャッシュされた結果を返すことで構成される最適化手法です。

無制限のバージョンがあり、これまでに表示される(入力引数、戻り値)のペアをキャッシュします。限定バージョン。LRUキャッシュを使用して、最後に表示されたN個の入力引数とその結果をキャッシュします。

メソッドのメモ化:

import groovy.transform.Memoized

@Memoized
Number factorial(Number n) {
    n == 0 ? 1 : factorial(n - 1)
}

@Memoized(maxCacheSize=1000)
Map fooDetails(Foo foo) {
    // call expensive service here
}

クロージャのメモ化:

def factorial = {Number n ->
    n == 0 ? 1 : factorial(n - 1)
}.memoize()

fooDetails = {Foo foo ->
    // call expensive service here
}.memoizeAtMost(1000)

ウィキペディアのページ コンピュータサイエンスでのメモ化の使用に関する広範な情報があります。簡単な実用的な使い方を1つだけ指摘します。

定数の初期化を可能な限り最後の瞬間まで延期する

クラス定義時または作成時に初期化できない定数値がある場合があります。たとえば、定数式は、別の定数または別のクラスのメソッドを使用する場合があります。これらは、クラスの初期化後に他の何か(Springなど)によってプラグインされます。

この場合、定数をゲッターに変換し、@Memoizedで装飾することができます。最初にアクセスされたときに1回だけ計算され、次に値がキャッシュされて再利用されます。

import groovy.transform.Memoized

@Memoized
def getMY_CONSTANT() {
    // compute the constant value using any external services needed
}
3
Tobia

GroovyはJavascriptのように機能します。クロージャーを介してプライベート変数と関数を持つことができます。クロージャ付きの関数をカレーすることもできます。

class FunctionTests {

def privateAccessWithClosure = {

    def privVar = 'foo'

    def privateFunc = { x -> println "${privVar} ${x}"}

    return {x -> privateFunc(x) } 
}


def addTogether = { x, y ->
    return x + y
}

def curryAdd = { x ->
    return { y-> addTogether(x,y)}
}

public static void main(String[] args) {
    def test = new FunctionTests()

    test.privateAccessWithClosure()('bar')

    def curried = test.curryAdd(5)

    println curried(5)
}
}

出力:

foo bar 10

2
Jason

動的メソッド呼び出し

名前の付いた文字列を使用してメソッドを呼び出すことができます

class Dynamic {
    def one() { println "method one()" }
    def two() { println "method two()" }
}

def callMethod( obj, methodName ) {
    obj."$methodName"()
}

def dyn = new Dynamic()

callMethod( dyn, "one" )               //prints 'method one()'
callMethod( dyn, "two" )               //prints 'method two()'
dyn."one"()                            //prints 'method one()'
2
lifeisfoo

Groovyの数行でJSONツリーを構築する方法は?

1)自己参照withDefaultクロージャーを使用してツリーを定義します

def tree // declare  first before using a self reference
tree = { ->  [:].withDefault{ tree() } }

2)独自のJSONツリーを作成します

frameworks = tree()
frameworks.grails.language.name = 'groovy'
frameworks.node.language.name = 'js'

def result =  new groovy.json.JsonBuilder(frameworks)

これは次のようになります:{"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}

2
ludo_rj

安全なナビゲーション演算子

セーフナビゲーション演算子は、NullPointerExceptionを回避するために使用されます。通常、オブジェクトへの参照がある場合は、オブジェクトのメソッドまたはプロパティにアクセスする前に、それがnullでないことを確認する必要があります。これを回避するために、安全なナビゲーションオペレーターは、次のように、例外をスローする代わりに単にnullを返します。

def person = Person.find { it.id == 123 }        // find will return a null instance    
def name = person?.name                          // use of the null-safe operator prevents from a NullPointerException, result is null
2
Pankaj Shinde

複数の変数の減速

1)1行での複数の変数宣言

def (a,b,c) = [1,2,3]

2)異なる型宣言を使用する。

def (String a, int b) = ['Groovy', 1]
1

エルビス演算子

"エルビス演算子"は三項演算子の短縮形です。これが便利な例の1つは、式がfalseに解決された場合に「適切なデフォルト」値を返す場合です(Groovyの真実のように)。簡単な例は次のようになります。

三項演算子を使用すると、割り当てたい値を繰り返す必要があります

displayCity = user.city ? user.city: 'UnKnown City'

エルビス演算子を使用すると、テストされた値がfalseでない場合に使用されます

displayCity = user.city ?: 'UnKnown City'
0
Ishwor

強制演算子

強制演算子(as)は、キャストの変形です。 Coercionは、オブジェクトをあるタイプから別のタイプに変換しますが、割り当てに互換性はありません。例を見てみましょう:

整数x = 123
String s =(String)x
整数は文字列に割り当てることができないため、実行時にClassCastExceptionが生成されますこれは、代わりに強制を使用して修正できます。

整数x = 123文字列s = x as String
整数を文字列に割り当てることはできませんが、asを使用すると文字列に強制変換されます

0
Ishwor