let's go developer 2011 sendai let's go java developer (programming language groovy part)
DESCRIPTION
レッツゴーデベロッパー2011発表資料、レッツゴーJavaデベロッパー「プログラミング言語Groovy編」TRANSCRIPT
Java
プログラミング言語Groovy編
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
自己紹介上原潤二NTTソフトウェア株式会社技術評論社刊行予定「プログラミングGroovy」3、5、8章執筆JGGUG運営委員ブログ“Grな日々”“Grails徹底入門”2章執筆GroovyServ開発者
22011年5月28日土曜日
2011 05/28 仙台Slide #
Java
本パートの内容
3
例1: ワードカウント処理例2: 変更不能クラスを定義するGroovyの設計理念(私見)まとめ宮本武蔵になろう!
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
例1:ワードカウント処理
4
引数で与えたテキストファイル中の単語の頻度を数える
$ cat input.txt That that is is that that isnot is not is that it it is
$ java WordCount input.txt 1: [That]2: [not]2: [it]4: [that]6: [is]
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Java版WordCount:48行
import java.util.Comparator;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.List;import java.util.Arrays;import java.io.FileReader;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.IOException;
public class WordCount { @SuppressWarnings(value = "unchecked") public static void main(String[] args) { FileReader fis = null; BufferedReader br = null; try { HashMap<String, Integer> map = new HashMap<String, Integer>(); fis = new FileReader(args[0]); br = new BufferedReader(fis); String line; while ((line = br.readLine()) != null) { for (String it: line.split("\\s+")) { map.put(it, (map.get(it)==null) ? 1 : (map.get(it) + 1)); } }
Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); Object[] list = entrySet.toArray(); Comparator comp = new Comparator(){ public int compare(Object o1, Object o2) { Map.Entry<String, Integer> e1 = (Map.Entry<String, Integer>) o1; Map.Entry<String, Integer> e2 = (Map.Entry<String, Integer>) o2; return e1.getValue() - e2.getValue(); } }; Arrays.sort(list, comp); for (Object it: list) { Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>)it; System.out.println(entry.getValue() + ": ["+entry.getKey()+"]"); } } catch (IOException e) { try {if (br != null) br.close();}catch(IOException ioe){} try {if (fis != null)fis.close();}catch(IOException ioe){} e.printStackTrace(); } }}
52011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} new File(args[0]).eachLine { it.split(/\s+/).each { map[it]++ } } map.entrySet().sort{it.value}.each { println "${it.value}: [${it.key}]" }
6
これだけですよ!これだけ
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Java版からボイラープレートコードを除去
import java.util.Comparator;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.List;import java.util.Arrays;import java.io.FileReader;import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.IOException;
public class WordCount { @SuppressWarnings(value = "unchecked") public static void main(String[] args) { FileReader fis = null; BufferedReader br = null; try { HashMap<String, Integer> map = new HashMap<String, Integer>(); fis = new FileReader(args[0]); br = new BufferedReader(fis); String line; while ((line = br.readLine()) != null) { for (String it: line.split("\\s+")) { map.put(it, (map.get(it)==null) ? 1 : (map.get(it) + 1)); } }
Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); Object[] list = entrySet.toArray(); Comparator comp = new Comparator(){ public int compare(Object o1, Object o2) { Map.Entry<String, Integer> e1 = (Map.Entry<String, Integer>) o1; Map.Entry<String, Integer> e2 = (Map.Entry<String, Integer>) o2; return e1.getValue() - e2.getValue(); } }; Arrays.sort(list, comp); for (Object it: list) { Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>)it; System.out.println(entry.getValue() + ": ["+entry.getKey()+"]"); } } catch (IOException e) { try {if (br != null) br.close();}catch(IOException ioe){} try {if (fis != null)fis.close();}catch(IOException ioe){} e.printStackTrace(); } }}
7「プログラムの動
作記述」を抽出するとこれだけ
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
82011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
9
セミコロン、主なパッケージのimport、チェック例外のtry-catchなど省略可能。
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
10
[:]はマップのリテラル。[a:1, b:2]の様に書ける。ちなみにリストのリテラルは[1,2,3]の様に書ける。
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
11
eachLineはクロージャを引数にとるjava.io.Fileクラスの追加メソッド。1行ごと読み取り、最後に自動クローズ処理。
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
12
mapのキーが存在しないときの初期値は通常Javaと同じくnullだが、withDefaultで0に変更することで++が使える
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
13
sortに比較ロジックをクロージャで渡し、ソート。逆順なら sort {-it.value }で。
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版WordCount(9行)
def map = [:].withDefault{0} // valueのデフォルト値が0のマップmapnew File(args[0]).eachLine { // 引数に与えたファイルの各行に対し、 it.split(/\s+/).each { // 正規表現/\s+/で区切り、それぞれに対し map[it]++ // それをmapのキーとする値に1を足す }}map.entrySet().sort{it.value}.each {// mapのentrySetをvalueでソート println "${it.value}: [${it.key}]"// それぞれのkey,valueを表示}
14
文字列定数中の $変数名、${式} はその値に展開される。(GString)
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
例2:変更不能クラスを定義する
15
フィールドの値を変更できない(Immutable)クラスを定義する
参考: Effective Java (2nd Edition), p73: Item15 Minimize mutability
クラスはfinal宣言全フィールドをfinalかつprivateにgetterメソッドの定義Mutableなデータ型(配列やStringBufferやDateなど)のフィールドに対しては「防御的コピー」を行うすべてのフィールドを初期化するコンストラクタを定義するフィールドの値に基づくequals, hashCode, toStringを定義する
2011年5月28日土曜日
public final class Person { private final String firstName; private final String lastName;
public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true;
if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false; return true; }
@Override public String toString() { return "Person(firstName:" + firstName + ", lastName:" + lastName + ")"; }
}
2011 05/28 仙台Slide #
Java
Java版 変更不能クラス: 57行
16
参考: http://groovy.codehaus.org/Immutable+AST+Macro
2011年5月28日土曜日
public final class Person { private final String firstName; private final String lastName;
public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true;
if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false; return true; }
@Override public String toString() { return "Person(firstName:" + firstName + ", lastName:" + lastName + ")"; }
}
2011 05/28 仙台Slide #
Java
Java版 変更不能クラス: 57行
16
作成が大変、ミスが混入しやすく、
意図がコード上明確ではない
参考: http://groovy.codehaus.org/Immutable+AST+Macro
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版変更不能クラス: 4行
@Immutableclass Person { String firstName, lastName}
17
これだけですよ!これだけ
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版変更不能クラス: 4行
@Immutableclass Person { String firstName, lastName}
17
これだけですよ!これだけ
x = new Person("Junji","Uehara")assert x.lastName == "Uehara"x.firstName = "abc" //==> groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: firstName for class: Person
2011年5月28日土曜日
x = new Person("Junji","Uehara")assert x.lastName == "Uehara"x.firstName = "abc"
2011 05/28 仙台Slide #
Java
Groovy版変更不能クラス: 4行
@Immutableclass Person { String firstName, lastName}
18
Groovyではフィールドを定義するだけでgetter,setterが自動生成される。(この場合はgetterのみ)
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版変更不能クラス: 4行
@Immutableclass Person { String firstName, lastName}
19
フィールドの参照はgetterメソッドの呼び出しとみなされる。
x = new Person("Junji","Uehara")assert x.lastName == "Uehara"x.firstName = "abc"
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovy版変更不能クラス: 4行
@Immutableclass Person { String firstName, lastName}
20
フィールドへの代入はsetterメソッドへの呼び出しとみなされる。
x = new Person("Junji","Uehara")assert x.lastName == "Uehara"x.firstName = "abc"
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovyの設計理念(私見)Javaへの愛(類似)
Javaへの憎しみ(差異)
212011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovyの設計理念(私見)Javaへの愛(類似)
Javaへの憎しみ(差異)
21
文法親和性、JVM共通、Groovyクラス=Javaクラス、ツール・ライブラリ共通・・・
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovyの設計理念(私見)Javaへの愛(類似)
Javaへの憎しみ(差異)
21
文法親和性、JVM共通、Groovyクラス=Javaクラス、ツール・ライブラリ共通・・・
何を違いとするか? 差別化するか?
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovyの設計理念(私見)Javaへの愛(類似)
Javaへの憎しみ(差異)
21
文法親和性、JVM共通、Groovyクラス=Javaクラス、ツール・ライブラリ共通・・・
何を違いとするか? 差別化するか?
その人を知りたければ
その人が
何に対して怒りを感じる
かを知るべし…ゴン 言語を知り
たければその言語が
何に対して怒りを感じる
かを知るべし
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
Groovyの設計理念(私見)Javaへの愛(類似)
Javaへの憎しみ(差異)
21
ボイラープレートコードをとことん排除する!! 憎しみすら感じる程に・・。
文法親和性、JVM共通、Groovyクラス=Javaクラス、ツール・ライブラリ共通・・・
何を違いとするか? 差別化するか?
その人を知りたければ
その人が
何に対して怒りを感じる
かを知るべし…ゴン 言語を知り
たければその言語が
何に対して怒りを感じる
かを知るべし
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
まとめJava+Groovyが一体となってJava技術の適用領域を広げる
22
JavaC Ruby
HaskelPHP
C++Python
Java + Groovy
システム記述 アプリケーション記述
ミドルウェアOS記述DSLデバイスドライバ記述
ハイパフォーマンス
2011年5月28日土曜日
2011 05/28 仙台Slide #
Java
宮本武蔵になろう!
23
Java Groovy
2011年5月28日土曜日