from old java to java8 - KanJava Edition

91
from old Java to modern Java ~ レビューで学ぶJava8時代のコーディング作法 Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会 谷本 心 ( @cero_t )
  • Upload

    -
  • Category

    Software

  • view

    1.202
  • download

    0

Transcript of from old java to java8 - KanJava Edition

Page 1: from old java to java8 - KanJava Edition

from old Java to modern Java

~ レビューで学ぶJava8時代のコーディング作法

Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会

谷本 心 ( @cero_t )

Page 2: from old java to java8 - KanJava Edition

自己紹介• 名前 : 谷本 心 (たにもと しん)

• 職業 : Javaエンジニア / トラブルシューター   トラブルシュート教育も引き受けます!

• Twitter : @cero_t

• その他 : 日本Javaユーザ会(JJUG) 幹事    関西Javaエンジニアの会 主催

Page 3: from old java to java8 - KanJava Edition

さて、Java8が出ましたが

Page 4: from old java to java8 - KanJava Edition

今日は関ジャバ∞と考えて

差し支えないですか?

Page 5: from old java to java8 - KanJava Edition

Page 6: from old java to java8 - KanJava Edition
Page 7: from old java to java8 - KanJava Edition
Page 8: from old java to java8 - KanJava Edition

自己紹介• 名前 : 谷本 心 (たにもと しん)

• 職業 : Javaエンジニア / トラブルシューター   トラブルシュート教育も引き受けます!

• Twitter : @cero_t

• その他 : 日本Javaユーザ会(JJUG) 幹事    関西Javaエンジニアの会 主催

Page 9: from old java to java8 - KanJava Edition

さて、Java8が出ましたが

Page 10: from old java to java8 - KanJava Edition

「どうせ、使うのはまだ先」とか思ってませんか?

Page 11: from old java to java8 - KanJava Edition

きっと、ずっと先でしょう。

Page 12: from old java to java8 - KanJava Edition

でも、たとえば今

Page 13: from old java to java8 - KanJava Edition

Java6やJava7の勉強をきちんとできますか?

Page 14: from old java to java8 - KanJava Edition

出始めこそ、たくさん情報が出てくる

Page 15: from old java to java8 - KanJava Edition

じゃ、いつやるか?

Page 16: from old java to java8 - KanJava Edition

やらせねーよ (我が家)

Page 17: from old java to java8 - KanJava Edition

from old Java to modern Java

~ レビューで学ぶJava8時代のコーディング作法

Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会

谷本 心 ( @cero_t )

Page 18: from old java to java8 - KanJava Edition

ソースコードレビューしてますか?

Page 19: from old java to java8 - KanJava Edition

レビューをする方が多いですか?受ける方が多いですか?

Page 20: from old java to java8 - KanJava Edition

もちろんレビューする方が多いですね

Page 21: from old java to java8 - KanJava Edition

若いんで(?)レビューを受ける方が

多いです

Page 22: from old java to java8 - KanJava Edition

レビューなんて文化 ありません

Page 23: from old java to java8 - KanJava Edition

履歴書の送付先 :[email protected]

Page 24: from old java to java8 - KanJava Edition

では早速、コード。

Page 25: from old java to java8 - KanJava Edition

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())); }

Page 26: from old java to java8 - KanJava Edition

何これ読めない

Page 27: from old java to java8 - KanJava Edition

「よく分からないしfor文とmapで

書き直してくれる?」

Page 28: from old java to java8 - KanJava Edition

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; }

Page 29: from old java to java8 - KanJava Edition

「あー、読みやすくて安心するー」

Page 30: from old java to java8 - KanJava Edition

Welcome to老 害 世 代

Page 31: from old java to java8 - KanJava Edition

from old Java to modern Java

~ 老害にならないためのJava8入門

Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会

谷本 心 ( @cero_t )

Page 32: from old java to java8 - KanJava Edition

Lesson1 今の時代のファイル操作を

理解せよ!

Page 33: from old java to java8 - KanJava Edition

おさらい: finallyでcloseするという定石

Page 34: from old java to java8 - KanJava Edition

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; }

これあかんやつや!

Page 35: from old java to java8 - KanJava Edition

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ですよね!

Page 36: from old java to java8 - KanJava Edition

finallyでcloseするのは古い定石

(~Java6)

Page 37: from old java to java8 - KanJava Edition

try-with-resourcesでイマドキのJavaに!(Java7~)

Page 38: from old java to java8 - KanJava Edition

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!

Page 39: from old java to java8 - KanJava Edition

でも! 変なところがあるんです。

Page 40: from old java to java8 - KanJava Edition

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; }

!?

Page 41: from old java to java8 - KanJava Edition

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; }

Page 42: from old java to java8 - KanJava Edition

新定石①: try-with-resourcesと FilesとPathで操作する

(Java7~)

Page 43: from old java to java8 - KanJava Edition

新定石②:ファイルを一気に読むならFiles.readAllLines!

(Java7~)

Page 44: from old java to java8 - KanJava Edition

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); } }

一気に読み込むのは便利だけど、ヒープメモリもたくさん使っちゃうし、それぞれの行に対する処理が必要な場合は、どうしてもループを回し直さなきゃいけないよね。

Page 45: from old java to java8 - KanJava Edition

Java8時代は?

Page 46: from old java to java8 - KanJava Edition

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;}

Page 47: from old java to java8 - KanJava Edition

新定石③?: Files.linesで処理をする

(Java8~)

Page 48: from old java to java8 - KanJava Edition

新定石③: forやwhileを見たらStream APIへの置き換えを考える

Page 49: from old java to java8 - KanJava Edition

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); } }

外部のオブジェクトを操作しない方が安心。

Page 50: from old java to java8 - KanJava Edition

ちょっとクイズ

Page 51: from old java to java8 - KanJava Edition

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); } }

Page 52: from old java to java8 - KanJava Edition

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. 実行時例外が起きるよ、これ

Page 53: from old java to java8 - KanJava Edition

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. 実行時例外が起きるよ、これ

Page 54: from old java to java8 - KanJava Edition

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); } }

Page 55: from old java to java8 - KanJava Edition

なんでもかんでもLambdaにすれば良いってもんでもない

Page 56: from old java to java8 - KanJava Edition

Lesson2文字列操作はどう変わる?

Page 57: from old java to java8 - KanJava Edition

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とか使うよねー

Page 58: from old java to java8 - KanJava Edition

String joinSE8(List<String> lines) { return String.join(",", lines); }

ようやく搭載されたString#join

Page 59: from old java to java8 - KanJava Edition

新定石④: String.joinさんこんにちは!(Java8~)

Page 60: from old java to java8 - KanJava Edition

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(); }

じゃ、こういうパターンはどうするの?

Page 61: from old java to java8 - KanJava Edition

private String joinPrefixCommons(List<String> lines) { return "<" + StringUtils.join(lines, ">,<") + ">"; }

private String joinPrefixGuava(List<String> lines) { return "<" + Joiner.on(">,<").join(lines) + ">"; }

Page 62: from old java to java8 - KanJava Edition

助けてJava8マン!

Page 63: from old java to java8 - KanJava Edition

private String joinPrefixSE8(List<String> lines) { return lines.stream() .map(s -> "<" + s +”>") .collect(Collectors.joining(",")); }

要するにStreamAPIが正義

Page 64: from old java to java8 - KanJava Edition

新定石⑤: String.joinさんさようなら!(Java8~)

Page 65: from old java to java8 - KanJava Edition

結局、新定石③: forやwhileを見たらStream APIへの置き換えを考える

Page 66: from old java to java8 - KanJava Edition

Lesson3 forやwhileとifとか

いろいろ行なう集計的なアレ

Page 67: from old java to java8 - KanJava Edition

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ドルを超える社員の数を部署ごとに集計する

Page 68: from old java to java8 - KanJava Edition

Java8時代は、最初、こうなると思う

Page 69: from old java to java8 - KanJava Edition

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

Page 70: from old java to java8 - KanJava Edition

でも、新定石③: forやwhileを見たらStream APIへの置き換えを考える

Page 71: from old java to java8 - KanJava Edition

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())); }

Page 72: from old java to java8 - KanJava Edition

どうやって書くの? どうやって読むの?

Page 73: from old java to java8 - KanJava Edition

select DEPT_ID, COUNT(EMP_ID) from EMP where EMP.SAL > 1000 group by EMP.DEPT_ID

Page 74: from old java to java8 - KanJava Edition

SQLと一緒。勉強して、書いて、書いて、書いて、そして、書く。

Page 75: from old java to java8 - KanJava Edition

input : List<Emp>

output : Map<Dept, Empの数>     ただしEmpは給与が1000より大きい

1. いったん List<Emp> を Map<Dept, List<Emp>> にグルーピングする。

2. Mapの値であるList<Emp>を1000でフィルタリングする。

3. フィルタリング後のList<Emp>をカウントする。

Page 76: from old java to java8 - KanJava Edition

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; }

Page 77: from old java to java8 - KanJava Edition

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())); }

Page 78: from old java to java8 - KanJava Edition

正直、ちょっとAPIが足りない感じなので自分で追加すると良い(この辺は熟成待ち?)

http://blog.exoego.net/2013/12/control-collector-to-rule-stream-api.html Collectorを征す者はStream APIを征す(部分的に) - I am programmer and proud

Page 79: from old java to java8 - KanJava Edition

検索: ラムダ禁止

Page 80: from old java to java8 - KanJava Edition

まとめ

Page 81: from old java to java8 - KanJava Edition

forとwhileを見たらLambda化を考えよう

Page 82: from old java to java8 - KanJava Edition

レビューでforとwhileを見つけたらLambda化させよう

Page 83: from old java to java8 - KanJava Edition

レビューで100行ぐらいの

Lambdaが出てきたら

Page 84: from old java to java8 - KanJava Edition

Page 85: from old java to java8 - KanJava Edition

自分たちの標準としてどうすれば読みやすくするか

チームで考えよう!

Page 86: from old java to java8 - KanJava Edition

from old Java to modern Java

~ 老害にならないためのJava8入門

Acroquest Technology株式会社 JJUG / 関西Javaエンジニアの会

谷本 心 ( @cero_t )

Page 87: from old java to java8 - KanJava Edition

あ、そうそう

Page 88: from old java to java8 - KanJava Edition

from old Javato modern Java

がきっかけで

Page 89: from old java to java8 - KanJava Edition

Java本格入門(仮) 鋭意執筆中!

Page 90: from old java to java8 - KanJava Edition

頑張ります m(_ _)m

Page 91: from old java to java8 - KanJava Edition

Let’s Study Java8!