ラベル Groovy の投稿を表示しています。 すべての投稿を表示
ラベル Groovy の投稿を表示しています。 すべての投稿を表示

2017年2月27日月曜日

String.formatは遅いのか (Java/Groovy)

String.formatは遅いのか?

ログの出力の際にも、よく使うString.format だが、
使いやすいが故に気にせず使っていたところ、String.formatは遅いという噂を聞いたので、どのくらい遅いのか比較してみた。
どうやら、内部でFormatterのインスタンスが毎回生成されているために遅いそうだ。。

2017年2月20日月曜日

整数の均等分割 (Groovy)

整数を均等に分割する

なるべく均等に整数を指定の数に分割する関数。
マッチングの処理なんかで使う事があったので、
その時に実装したものを。
検索すると既にいっぱい出て来たので、
あまり需要はないかもと、思いつつも自分のメモとして残しておく。
標準ライブラリにあってもいい気がするんですが、
僕は見つけられなかったです…。
何処かにあったりしないのかな?


2017年1月31日火曜日

Groovyでプロジェクトを作る (gradle)

groovyでプロジェクトを作る際に最低限必要なbuild.graldeを紹介。
gradleプロジェクトの作成
gradle init
カレントディレクトリに、build.gradleや、gradlew などのファイルが生成される。

2017年1月14日土曜日

Map ワイルドカードアクセス (Groovy)

Groovy
Mapオブジェクトの値取得にワイルドカードを使用してアクセスする関数を実装する。

import groovy.json.*

String json = '''
{
  "reward_id_1": 100,
  "reward_id_2": 200,
  "reward_id_3": 300,
  "other1": 10,
  "other2": 20,
  "other3": 30
}
'''

Map propertyMap(obj, String property) {
    property = property.replace("*", ".*")
    return obj.keySet()
        .findAll({ it ==~ /${property}/ })
        .collectEntries([:] as LinkedHashMap, { p -> ["$p": obj."$p"] })
}


def obj = new JsonSlurper().parseText(json)
println obj
// ==> [other1:10, other2:20, other3:30, reward_id_1:100, reward_id_2:200, reward_id_3:300]

println propertyMap(obj, "reward_id_*")
// ==> [reward_id_1:100, reward_id_2:200, reward_id_3:300]

propertyMap(obj, "reward_id_*").each { key, rewardId ->
    println rewardId
}
// ==> 100
// ==> 200
// ==> 300

propertyMapという関数に、ワイルドカードで指定したキー名を渡すと、マップにして返してくれます。
後々、連番が増えたりしても修正しなくてよいので便利かと。。


追記:
オブジェクトに対してfindAllだけで、実現できる事に気づいた。
Map propertyMap(obj, String property) {
    property = property.replace("*", ".*")
    obj.findAll { it ==~ /${property}/ }
}

ワイルドカードではなく正規表現をそのまま使うのであれば、下記一行のみでOKだった。。
it には Entryのオブジェクトが渡っているけど、マッチ演算時ではkey名で評価されているみたい。
println obj.findAll { it ==~ /reward_id_.*/ }
// ==> [reward_id_1:100, reward_id_2:200, reward_id_3:300]

最終的には、わざわざ関数作らなくても既存のGroovyメソッドで事足りるんですね。
Groovyすごいな〜

2017年1月9日月曜日

Groovy each

Groovy のクラスオブジェクトは、 デフォルトでeachメソッドを備えているようで、別に配列でなくても、each が使える。

class Person{
    String name
}

def personList = [ new Person(name:"hoge"),
                                new Person(name:"piyo") ]

personList.each { println it.name }
// 出力結果
// ==> hoge
// ==> piyo
リスト配列のオブジェクトをeach できるのは当然だが、
下記のように、単一のオブジェクトでも、eachを使って動作させる事ができる。

def person = new Person(name:"foo")

person.each { println it.name }
// 出力結果
// ==> foo

メソッドの引数などで使えば、
単一オブジェクトの場合と、リストの場合で処理分けしなくてもよくなるぞ。

Groovy ループ内で生成したクロージャはカリー化して使え


下記のコードの出力結果は、すべて3となる。
def arr = []
for (int i=0; i<3; i++){
    arr << { println i }
}
arr.each { it() }

// 出力結果
// ==> 3
// ==> 3
// ==> 3
クロージャ内の出力関数が実行される時には変数i はすでにインクリメントされたものが出力されるようだ。。


変数i をクロージャの引数として渡すと、うまくいくようで
その為に、カリー化して変数を引数として渡しておく必要がある。
for (int i=0; i<3; i++){
   arr << { i_ -> println i_ }.curry(i)
}
arr.each { it() }

// 出力結果
// ==> 0
// ==> 1
// ==> 2

ループ内で書き換わる変数をクロージャ内で利用する際には、
カリー化して変数を固定しておかないと、あとで呼び出すときに困る。

2017年1月3日火曜日

GradleでビルドするとNoClassDefFoundErrorが発生する場合の対処 (Groovy)


Groovy で
FileNameFinderクラスや、CliBuilderを利用している時に
./gradlew run などで実行すると、NoClassDefFoundError が発生する場合がある。

どうやら、ant や commons-cli に依存しているようだが、
groovy-allであってもそれらは Optional Dependencies な為、
コンパイルする場合は明示的に依存解決しておかないと駄目みたい。。
(たぶんそういう事だと思う)

gradleで依存解決を記載するのは、
下記のように(build.gradleの) dependencies に ant / commons-cli を追記すればOK

dependencies {
    compile "org.codehaus.groovy:groovy-all:2.4.7"
    compile "org.apache.ant:ant:1.9.7"
    compile "commons-cli:commons-cli:1.3.1"
}

# ant
https://mvnrepository.com/artifact/org.apache.ant/ant/1.9.7

# commons-cli
https://mvnrepository.com/artifact/commons-cli/commons-cli/1.3.1

2016年9月3日土曜日

Groovy で DropBox API v2 を使ってみる

groovyを使って、DropBox API v2 を使って見る。

DropBox Java API のドキュメント
http://dropbox.github.io/dropbox-sdk-java/api-docs/v2.0.x/

Mavenリポジトリ
http://mvnrepository.com/artifact/com.dropbox.core/dropbox-core-sdk

dropboxApiTest.groovy:
@Grab(group='com.dropbox.core', module='dropbox-core-sdk', version='2.1.+')

import com.dropbox.core.*
import com.dropbox.core.v2.*
import java.util.Locale

final String USER_AGENT = "TestApp/1.0"
final String OAUTH2_ACCESS_TOKEN = "XXX"

def config = new DbxRequestConfig(USER_AGENT,Locale.getDefault().toString())
def client = new DbxClientV2(config, OAUTH2_ACCESS_TOKEN)

String accountName =client.users().getCurrentAccount().getName().getDisplayName()
int capacity = client.users().getSpaceUsage().getAllocation().getIndividualValue().getAllocated() / 1024 / 1024
int used     = client.users().getSpaceUsage().getUsed() / 1024 / 1024
println "name: ${accountName}"
println "size: ${used}/${capacity} MB"

println "files:"
client.files().listFolder("").getEntries().each {
    println it.getName()
}


あとは、実行するだけ。
groovy dropboxApiTest.groovy
Grabを使ってるので、初回のみライブラリのインストールが走ります。

USER_AGENT は、
APIリクエストする際のUserAgentヘッダとして使われる。なんでもよさそうだが、"YourAppName/Version" としておくのが良いみたい。

OAUTH2_ACCESS_TOKEN は、
DropBox Developper Page > MyApps > YourApp > OAuth2 > Generated access token から作成する。

listFolder("") のところは、listFolder("/") としてしまうと、動かない。

あとで気付いたけど、
DropBox Developper Page > Documents > Java > Tutorial を見た方がわかりやすいかも。

こんな感じで出力されます。
name: tyabuta
size: 1096/3968 MB
files:
hoge.txt
piyo.txt