Upload
from old java to java8 - KanJava Edition
•
12 likes
•
2,877 views
心 谷本
Follow
from old Java to modern Java : reloaded for Kansai Java Engineers' Group
Read less
Read more
Report
Share
Report
Share
1 of 91
Download now
Download to read offline
More Related Content
from old java to java8 - KanJava Edition
1.
from old Java to
modern Java ∼ レビューで学ぶJava8時代のコーディング作法 Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会 谷本 心 ( @cero_t )
2.
自己紹介 • 名前 :
谷本 心 (たにもと しん) • 職業 : Javaエンジニア / トラブルシューター トラブルシュート教育も引き受けます! • Twitter : @cero_t • その他 : 日本Javaユーザ会(JJUG) 幹事 関西Javaエンジニアの会 主催
3.
さて、 Java8が出ましたが
4.
今日は 関ジャバ∞ と考えて 差し支えないですか?
5.
バ
8.
自己紹介 • 名前 :
谷本 心 (たにもと しん) • 職業 : Javaエンジニア / トラブルシューター トラブルシュート教育も引き受けます! • Twitter : @cero_t • その他 : 日本Javaユーザ会(JJUG) 幹事 関西Javaエンジニアの会 主催
9.
さて、 Java8が出ましたが
10.
「どうせ、使うのはまだ先」 とか思ってませんか?
11.
きっと、ずっと先でしょう。
12.
でも、たとえば今
13.
Java6やJava7の勉強を きちんとできますか?
14.
出始めこそ、 たくさん情報が出てくる
15.
じゃ、いつやるか?
16.
やらせねーよ (我が家)
17.
from old Java to
modern Java ∼ レビューで学ぶJava8時代のコーディング作法 Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会 谷本 心 ( @cero_t )
18.
ソースコードレビュー してますか?
19.
レビューを する方が多いですか? 受ける方が多いですか?
20.
もちろん レビューする方が 多いですね
21.
若いんで(?) レビューを受ける方が 多いです
22.
レビューなんて文化 ありません
23.
履歴書の送付先 : tanimoto.shin@gmail.com
24.
では早速、コード。
25.
Map<Dept, Long> groupByDeptAndFilter(List<Emp>
list) { return list.stream() .collect(Collectors.groupingBy(emp -> emp.dept)) .entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .filter(emp -> emp.sal > 1000) .count())); }
26.
何これ読めない
27.
「よく分からないし for文とmapで 書き直してくれる?」
28.
Map<Dept, Long> groupByDeptClassic(List<Emp>
list) { Map<Dept, Long> result = new HashMap<>(); for (Emp emp : list) { if (result.containsKey(emp.dept) == false) { result.put(emp.dept, 0L); } if (emp.sal > 1000) { Long count = result.get(emp.dept); count++; result.put(emp.dept, count); } } return result; }
29.
「あー、読みやすくて 安心するー」
30.
Welcome to 老 害
世 代
31.
from old Java to
modern Java ∼ 老害にならないためのJava8入門 Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会 谷本 心 ( @cero_t )
32.
Lesson1 今の時代のファイル操作を 理解せよ!
33.
おさらい: finallyでcloseするという定石
34.
List<String> readFileSE6(String fileName)
{ List<String> lines = new ArrayList<String>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(fileName)); String line; while ((line = reader.readLine()) != null) { lines.add("<" + line + ">"); } reader.close(); } catch (IOException ex) { throw new RuntimeException(ex); } return lines; } これあかん やつや!
35.
List<String> readFileSE6(String fileName)
{ List<String> lines = new ArrayList<String>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(fileName)); String line; while ((line = reader.readLine()) != null) { lines.add("<" + line + ">"); } } catch (IOException ex) { throw new RuntimeException(ex); // 例外処理は割愛 } finally { try { if (reader != null) { reader.close(); } } catch (IOException ex) { // この例外は無視する? } } return lines; } やっぱfinallyで closeですよね!
36.
finallyでcloseするのは 古い定石 (∼Java6)
37.
try-with-resourcesで イマドキのJavaに! (Java7∼)
38.
List<String> readFileSE7_1(String fileName)
{ List<String> lines = new ArrayList<>(); try (FileReader in = new FileReader(fileName); BufferedReader reader = new BufferedReader(in)) { String line; while ((line = reader.readLine()) != null) { lines.add("<" + line + ">"); } } catch (IOException ex) { throw new RuntimeException(ex); } return lines; } これが try-with-resources!
39.
でも! 変なところがあるんです。
40.
List<String> readFileSE7_1(String fileName)
{ List<String> lines = new ArrayList<>(); try (FileReader in = new FileReader(fileName); BufferedReader reader = new BufferedReader(in)) { String line; while ((line = reader.readLine()) != null) { lines.add("<" + line + ">"); } } catch (IOException ex) { throw new RuntimeException(ex); } return lines; } !?
41.
List<String> readFileSE7_2(String fileName)
{ List<String> lines = new ArrayList<>(); Path path = Paths.get(fileName); try (BufferedReader reader = Files.newBufferedReader(path)) { String line; while ((line = reader.readLine()) != null) { lines.add("<" + line + ">"); } } catch (IOException ex) { throw new RuntimeException(ex); } return lines; }
42.
新定石①: try-with-resourcesと FilesとPathで操作する (Java7∼)
43.
新定石②: ファイルを一気に読むなら Files.readAllLines! (Java7∼)
44.
List<String> readFileSE7_3(String fileName)
{ try { List<String> lines = Files.readAllLines(Paths.get(fileName)); for (int i = 0; i < lines.size(); i++) { lines.set(i, "<" + lines.get(i) + ">"); } return lines; } catch (IOException ex) { throw new RuntimeException(ex); } } 一気に読み込むのは便利だけど、 ヒープメモリもたくさん使っちゃう し、それぞれの行に対する処理が 必要な場合は、どうしてもループを 回し直さなきゃいけないよね。
45.
Java8時代は?
46.
List<String> readFileSE8_1(String fileName)
{ List<String> lines = new ArrayList<>(); try { Files.lines(Paths.get(fileName)) .forEach(s -> lines.add("<" + s + ">")); } catch (IOException ex) { throw new UncheckedIOException(ex); } return lines; }
47.
新定石③?: Files.linesで処理をする (Java8∼)
48.
新定石③: forやwhileを見たら Stream APIへの 置き換えを考える
49.
List<String> readFileSE8_1(String fileName)
{ try { return Files.lines(Paths.get(fileName)) .map(s -> "<" + s + ">") .collect(Collectors.toList()); } catch (IOException ex) { throw new UncheckedIOException(ex); } } 外部のオブジェクトを 操作しない方が安心。
50.
ちょっとクイズ
51.
void writeSE8_1(String fileName,
List<String> lines) { Path path = Paths.get(fileName); try (BufferedWriter writer = Files.newBufferedWriter(path)) { lines.forEach(s -> writer.write("<" + s + ">")); } catch (IOException e) { throw new UncheckedIOException(ex); } }
52.
void writeSE8_1(String fileName,
List<String> lines) { Path path = Paths.get(fileName); try (BufferedWriter writer = Files.newBufferedWriter(path)) { lines.forEach(s -> writer.write("<" + s + ">")); } catch (IOException e) { throw new UncheckedIOException(ex); } } 1. ちゃんと出力されるんじゃない? 2. 順番がグチャグチャになりそうだな・・・ 3. コンパイルエラーが起きるよ、これ 4. 実行時例外が起きるよ、これ
53.
void writeSE8_1(String fileName,
List<String> lines) { Path path = Paths.get(fileName); try (BufferedWriter writer = Files.newBufferedWriter(path)) { lines.forEach(s -> writer.write("<" + s + ">")); } catch (IOException e) { throw new UncheckedIOException(ex); } } 1. ちゃんと出力されるんじゃない? 2. 順番がグチャグチャになりそうだな・・・ 3. コンパイルエラーが起きるよ、これ 4. 実行時例外が起きるよ、これ
54.
void writeSE8_2(String fileName,
List<String> lines) { Path path = Paths.get(fileName); try (BufferedWriter writer = Files.newBufferedWriter(path)) { lines.forEach(s -> { try { writer.write(s); } catch (IOException ex) { throw new UncheckedIOException(ex); } }); } catch (IOException ex) { throw new UncheckedIOException(ex); } }
55.
なんでもかんでも Lambdaにすれば 良いってもんでもない
56.
Lesson2 文字列操作は どう変わる?
57.
String joinSE7(List<String> lines)
{ StringBuilder builder = new StringBuilder(); for (int i = 0; i < lines.size(); i++) { if (i > 0) { builder.append(","); } builder.append(lines.get(i)); } return builder.toString(); } String joinCommons(List<String> lines) { return StringUtils.join(lines, ","); } String joinGuava(List<String> lines) { return Joiner.on(",").join(lines); } みんな大好き 文字列結合 Commons Langとか Guavaとか使うよねー
58.
String joinSE8(List<String> lines)
{ return String.join(",", lines); } ようやく搭載された String#join
59.
新定石④: String.joinさん こんにちは! (Java8∼)
60.
String joinPrefixSE7(List<String> lines)
{ StringBuilder builder = new StringBuilder(); for (int i = 0; i < lines.size(); i++) { if (i > 0) { builder.append(","); } builder.append(“<") .append(lines.get(i)) .append(">"); } return builder.toString(); } じゃ、こういうパター ンはどうするの?
61.
private String joinPrefixCommons(List<String>
lines) { return "<" + StringUtils.join(lines, ">,<") + ">"; } private String joinPrefixGuava(List<String> lines) { return "<" + Joiner.on(">,<").join(lines) + ">"; }
62.
助けてJava8マン!
63.
private String joinPrefixSE8(List<String>
lines) { return lines.stream() .map(s -> "<" + s +”>") .collect(Collectors.joining(",")); } 要するに StreamAPIが正義
64.
新定石⑤: String.joinさん さようなら! (Java8∼)
65.
結局、新定石③: forやwhileを見たら Stream APIへの 置き換えを考える
66.
Lesson3 forやwhileとifとか いろいろ行なう集計的なアレ
67.
Map<Dept, Long> groupByDeptAndFilterClassic(List<Emp>
list) { Map<Dept, Long> result = new HashMap<>(); for (Emp emp : list) { if (result.containsKey(emp.dept) == false) { result.put(emp.dept, 0L); } if (emp.sal > 1000) { Long count = result.get(emp.dept) + 1; result.put(emp.dept, count); } } return result; } 給料が1000ドルを超える社員 の数を部署ごとに集計する
68.
Java8時代は、 最初、こうなると思う
69.
Map<Dept, Long> groupByDeptAndFilterClassic(List<Emp>
list) { Map<Dept, Long> result = new HashMap<>(); for (Emp emp : list) { result.putIfAbsent(emp.dept, 0L); if (emp.sal > 1000) { Long count = result.get(emp.dept) + 1; result.put(emp.dept, count); } } return result; } 新しい便利API
70.
でも、新定石③: forやwhileを見たら Stream APIへの 置き換えを考える
71.
Map<Dept, Long> groupByDeptAndFilterLambda(List<Emp>
list) { return list.stream() .collect(Collectors.groupingBy(emp -> emp.dept)) .entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .filter(emp -> emp.sal > 1000) .count())); }
72.
どうやって書くの? どうやって読むの?
73.
select DEPT_ID, COUNT(EMP_ID) from EMP where EMP.SAL >
1000 group by EMP.DEPT_ID
74.
SQLと一緒。 勉強して、書いて、 書いて、書いて、 そして、書く。
75.
input : List<Emp> output
: Map<Dept, Empの数> ただしEmpは給与が1000より大きい 1. いったん List<Emp> を Map<Dept, List<Emp>> にグルーピングする。 2. Mapの値であるList<Emp>を1000でフィルタリングする。 3. フィルタリング後のList<Emp>をカウントする。
76.
Map<Dept, Long> groupByDeptAndFilterLambda2(List<Emp>
list) { Map<Dept, List<Emp>> groupByDept = list.stream() .collect(Collectors.groupingBy(emp -> emp.dept)); Map<Dept, List<? super Emp>> filtered = groupByDept.entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .filter(emp -> emp.sal > 1000) .collect(Collectors.toList()))); Map<Dept, Long> counted = filtered.entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .count())); return counted; }
77.
Map<Dept, Long> groupByDeptAndFilterLambda(List<Emp>
list) { return list.stream() .collect(Collectors.groupingBy(emp -> emp.dept)) .entrySet() .stream() .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue() .stream() .filter(emp -> emp.sal > 1000) .count())); }
78.
正直、ちょっとAPIが 足りない感じなので 自分で追加すると良い (この辺は熟成待ち?) http://blog.exoego.net/2013/12/control-collector-to-rule-stream-api.html Collectorを征す者はStream APIを征す(部分的に) -
I am programmer and proud
79.
検索: ラムダ禁止
80.
まとめ
81.
forとwhileを見たら Lambda化を考えよう
82.
レビューで forとwhileを見つけたら Lambda化させよう
83.
レビューで 100行ぐらいの Lambdaが出てきたら
84.
…
85.
自分たちの標準として どうすれば読みやすくするか チームで考えよう!
86.
from old Java to
modern Java ∼ 老害にならないためのJava8入門 Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会 谷本 心 ( @cero_t )
87.
あ、そうそう
88.
from old Java to
modern Java がきっかけで
89.
Java本格入門(仮) 鋭意執筆中!
90.
頑張ります m(_ _)m
91.
Let s Study
Java8!
Download now