Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

20150302 java8 第一回_ラムダ式(1)

1.083 visualizaciones

Publicado el

Publicado en: Ingeniería
  • Inicia sesión para ver los comentarios

20150302 java8 第一回_ラムダ式(1)

  1. 1. Java 8 勉強会 第一回 ラムダ式 (1) 2015/3/2 開発部 3G 野口光太郎
  2. 2. ついに Java 8 が使える
  3. 3. Java 8 導入予定 • Thunderbus • 1.0 で導入済(8u31) • PIMSYNC • 2.2 で導入予定 • DataSpider Servista • 4.0 で導入予定
  4. 4. Java 8 の新機能 • ラムダ式 • Stream API • Date and Time API • JavaFX 8 • etc…
  5. 5. Java 8 の新機能 • ラムダ式 • Stream API • Date and Time API • JavaFX 8 • etc…
  6. 6. ついに ラムダ式 が使える
  7. 7. Java 8 勉強会 第一回 ラムダ式 (1) 2015/3/2 開発部 3G 野口光太郎
  8. 8. アジェンダ 1. ラムダ式は何が違うのか 2. ラムダ式を書く 3. forEach によるイテレーション
  9. 9. 1. ラムダ式は 何が 違うのか
  10. 10. ラムダ式とは • 匿名関数の簡略な記法 • Java 8(2014/3)で導入 • 取り立てて新しい概念ではない • C++11(2011 年) • C# 3.0(2008 年) • Lisp(ざっと 50 年くらい前)
  11. 11. ラムダ式とは • 匿名関数の簡略な記法 • Java 8(2014/3)で導入 • 取り立てて新しい概念ではない • C++11(2011 年) • C# 3.0(2008 年) • Lisp(ざっと 50 年くらい前)
  12. 12. 匿名関数の 簡略な記法 ……?
  13. 13. 匿名関数とは • 匿名の関数 • 要するにこれのこと List<Integer> numbers = Arrays.asList(1, 1, 2, 3, 5); Collections.sort(numbers, new Comparator<Integer>() { @Override public int compare(Integer i1, Integer i2) { return i2 - i1; } });
  14. 14. 匿名関数の簡略な記法 • こう書ける List numbers = Arrays.asList(1, 1, 2, 3, 5); Collections.sort(numbers, (i1, i2) -> i2 - i1);
  15. 15. で?
  16. 16. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, new Assertion() { @Override public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); }
  17. 17. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, new Assertion() { @Override public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); }
  18. 18. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, new Assertion() { @Override public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); } ノイズ ・new ・Assertion() ・@Override ・public ・void ・call テストの内容にとっては全部どうでもいい
  19. 19. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, new Assertion() { @Override public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); }
  20. 20. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, (expectedSheet, actualSheet, row, column) -> { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); } • こう書ける
  21. 21. Excel アダプタのテスト コードの例(Before) • こういうのも private interface Assertion { public void call(Sheet expectedSheet, Sheet actualSheet, int row, int column) throws Exception; } private void assertDataAndFormat(String expectedExcelFileName, String sheetName, int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex) throws Exception { assertWithExpectedExcelFile( expectedExcelFileName, sheetName, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex, (expectedSheet, actualSheet, row, column) -> { Cell expetedCell = expectedSheet.getCell(column, row); Cell actualCell = actualSheet.getCell(column, row); assertEquals(expetedCell.getContents(), actualCell.getContents()); assertEquals(expetedCell.getType().toString(), actualCell.getType().toString()); assertEquals(expetedCell.getCellFormat().getFormat().getFormatString(), actualCell.getCellFormat().getFormat().getFormatString()); AssertUtil.assertCellFormatByJExcelApi( expetedCell.getCellFormat(), actualCell.getCellFormat()); } } ); } Excel アダプタのテスト コードの例(After) (匿名関数) • こう書ける • メソッドに関数を直接渡せる
  22. 22. (注意) 実際に過去に書いたコードの中からノイズが減って 嬉しい例としてたまたまこれを思い出したので挙げ ましたが、関数型のスタイルという観点では、そも そもあまり長いラムダ式は推奨されない、という考 え方もあるようです。 あとそもそもアサーションの仕方がダサいとかは今 はツッコまない方向で……。
  23. 23. xxx アダプタのテスト コードの例(Before) • こういうのも @Test public void ソート_標準カラム_文書管理番号_昇順() throws Exception { ソート(STANDARD_COLUMN, MANAGE_NUM, TAG_DOC_NUM, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2){ return o1.getDocNum() - o2.getDocNum(); } }); }
  24. 24. xxx アダプタのテスト コードの例(Before) • こういうのも @Test public void ソート_標準カラム_文書管理番号_昇順() throws Exception { ソート(STANDARD_COLUMN, MANAGE_NUM, TAG_DOC_NUM, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { return o1.getDocNum() - o2.getDocNum(); } }); } @Test public void ソート_標準カラム_文書管理番号_降順() throws Exception { ソート(STANDARD_COLUMN, MANAGE_NUM, TAG_DOC_NUM, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { return o2.getDocNum() - o1.getDocNum(); } }); } 1
  25. 25. @Test public void ソート_標準カラム_文書名_昇順() throws Exception { ソート(STANDARD_COLUMN, DOC_NAME, TAG_DOC_NAME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getDocName(); String v2 = o2.getDocName(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_文書名_降順() throws Exception { ソート(STANDARD_COLUMN, DOC_NAME, TAG_DOC_NAME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getDocName(); String v2 = o2.getDocName(); return compareNull(v2, v1); } }); } @Test public void ソート_標準カラム_コンピューター名_昇順() throws Exception { ソート(STANDARD_COLUMN, COMPUTER_NAME, TAG_COMPUTER_NAME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getComputerName(); String v2 = o2.getComputerName(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_コンピューター名_降順() throws Exception { ソート(STANDARD_COLUMN, COMPUTER_NAME, TAG_COMPUTER_NAME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getComputerName(); String v2 = o2.getComputerName(); return compareNull(v2, v1); } }); } 2
  26. 26. @Test public void ソート_標準カラム_ユーザー名_昇順() throws Exception { ソート(STANDARD_COLUMN, USER_NAME, TAG_USER_NAME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getUserName(); String v2 = o2.getUserName(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_ユーザー名_降順() throws Exception { ソート(STANDARD_COLUMN, USER_NAME, TAG_USER_NAME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getUserName(); String v2 = o2.getUserName(); return compareNull(v2, v1); } }); } @Test public void ソート_標準カラム_印刷プリンター名_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINTER_NAME, TAG_PRINTER_NAME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getPrinterName(); String v2 = o2.getPrinterName(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_印刷プリンター名_降順() throws Exception { ソート(STANDARD_COLUMN, PRINTER_NAME, TAG_PRINTER_NAME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getPrinterName(); String v2 = o2.getPrinterName(); return compareNull(v2, v1); } }); } 3
  27. 27. @Test public void ソート_標準カラム_印刷プリンターグループ名_昇順() throws Exception { ソート(STANDARD_COLUMN, GROUP_NAME, TAG_PRINTER_GROUP_NAME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getPrinterGroupName(); String v2 = o2.getPrinterGroupName(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_印刷プリンターグループ名_降順() throws Exception { ソート(STANDARD_COLUMN, GROUP_NAME, TAG_PRINTER_GROUP_NAME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { String v1 = o1.getPrinterGroupName(); String v2 = o2.getPrinterGroupName(); return compareNull(v2, v1); } }); } @Test public void ソート_標準カラム_スプール開始時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_START_TIME, TAG_SPOOL_START_TIME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getSpoolStartTime(); Date v2 = o2.getSpoolStartTime(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_スプール開始時刻_降順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_START_TIME, TAG_SPOOL_START_TIME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getSpoolStartTime(); Date v2 = o2.getSpoolStartTime(); return compareNull(v2, v1); } }); } 4
  28. 28. @Test public void ソート_標準カラム_スプール終了時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_END_TIME, TAG_SPOOL_END_TIME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getSpoolEndTime(); Date v2 = o2.getSpoolEndTime(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_スプール終了時刻_降順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_END_TIME, TAG_SPOOL_END_TIME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getSpoolEndTime(); Date v2 = o2.getSpoolEndTime(); return compareNull(v2, v1); } }); } @Test public void ソート_標準カラム_印刷開始時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINT_START_TIME, TAG_PRINT_START_TIME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getPrintStartTime(); Date v2 = o2.getPrintStartTime(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_印刷開始時刻_降順() throws Exception { ソート(STANDARD_COLUMN, PRINT_START_TIME, TAG_PRINT_START_TIME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getPrintStartTime(); Date v2 = o2.getPrintStartTime(); return compareNull(v2, v1); } }); } 5
  29. 29. @Test public void ソート_標準カラム_印刷終了時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINT_END_TIME, TAG_PRINT_END_TIME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getPrintEndTime(); Date v2 = o2.getPrintEndTime(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_印刷終了時刻_降順() throws Exception { ソート(STANDARD_COLUMN, PRINT_END_TIME, TAG_PRINT_END_TIME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getPrintEndTime(); Date v2 = o2.getPrintEndTime(); return compareNull(v2, v1); } }); } @Test public void ソート_標準カラム_最終更新時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, UPDATE_TIME, TAG_UPDATE_TIME, 0, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getUpdateTime(); Date v2 = o2.getUpdateTime(); return compareNull(v1, v2); } }); } @Test public void ソート_標準カラム_最終更新時刻_降順() throws Exception { ソート(STANDARD_COLUMN, UPDATE_TIME, TAG_UPDATE_TIME, 1, new Comparator() { @Override public int compare(XXXDocument o1, XXXDocument o2) { Date v1 = o1.getUpdateTime(); Date v2 = o2.getUpdateTime(); return compareNull(v2, v1); } }); } 6
  30. 30. 22 テストケース 6 ページ 247 行
  31. 31. • こう書ける @Test public void ソート_標準カラム_文書管理番号_昇順() throws Exception { ソート(STANDARD_COLUMN, MANAGE_NUM, TAG_DOC_NUM, 0, (o1, o2) -> o1.getDocNum() - o2.getDocNum()); } @Test public void ソート_標準カラム_文書管理番号_降順() throws Exception { ソート(STANDARD_COLUMN, MANAGE_NUM, TAG_DOC_NUM, 1, (o1, o2) -> o2.getDocNum() - o1.getDocNum()); } @Test public void ソート_標準カラム_文書名_昇順() throws Exception { ソート(STANDARD_COLUMN, DOC_NAME, TAG_DOC_NAME, 0, (o1, o2) -> compareNull(o1.getDocName(), o2.getDocName()); } @Test public void ソート_標準カラム_文書名_降順() throws Exception { ソート(STANDARD_COLUMN, DOC_NAME, TAG_DOC_NAME, 1, (o1, o2) -> compareNull(o2.getDocName(), o1.getDocName()); } @Test public void ソート_標準カラム_コンピューター名_昇順() throws Exception { ソート(STANDARD_COLUMN, COMPUTER_NAME, TAG_COMPUTER_NAME, 0, (o1, o2) -> compareNull(o1.getComputerName(), o2.getComputerName()); } xxx アダプタのテスト コードの例(After) 1
  32. 32. @Test public void ソート_標準カラム_コンピューター名_降順() throws Exception { ソート(STANDARD_COLUMN, COMPUTER_NAME, TAG_COMPUTER_NAME, 1, (o1, o2) -> compareNull(o2.getComputerName(), o1.getComputerName()); } @Test public void ソート_標準カラム_ユーザー名_昇順() throws Exception { ソート(STANDARD_COLUMN, USER_NAME, TAG_USER_NAME, 0, (o1, o2) -> compareNull(o1.getUserName(), o2.getUserName()); } @Test public void ソート_標準カラム_ユーザー名_降順() throws Exception { ソート(STANDARD_COLUMN, USER_NAME, TAG_USER_NAME, 1, (o1, o2) -> compareNull(o2.getUserName(), o1.getUserName()); } @Test public void ソート_標準カラム_印刷プリンター名_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINTER_NAME, TAG_PRINTER_NAME, 0, (o1, o2) -> compareNull(o1.getPrinterName(), o2.getPrinterName()); } @Test public void ソート_標準カラム_印刷プリンター名_降順() throws Exception { ソート(STANDARD_COLUMN, PRINTER_NAME, TAG_PRINTER_NAME, 1, (o1, o2) -> compareNull(o2.getPrinterName(), o1.getPrinterName()); } @Test public void ソート_標準カラム_印刷プリンターグループ名_昇順() throws Exception { ソート(STANDARD_COLUMN, GROUP_NAME, TAG_PRINTER_GROUP_NAME, 0, (o1, o2) -> compareNull(o1.getPrinterGroupName(), o2.getPrinterGroupName()); } @Test public void ソート_標準カラム_印刷プリンターグループ名_降順() throws Exception { ソート(STANDARD_COLUMN, GROUP_NAME, TAG_PRINTER_GROUP_NAME, 1, (o1, o2) -> compareNull(o2.getPrinterGroupName(), o1.getPrinterGroupName()); } @Test public void ソート_標準カラム_スプール開始時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_START_TIME, TAG_SPOOL_START_TIME, 0, (o1, o2) -> compareNull(o1.getSpoolStartTime(), o2.getSpoolStartTime()); } @Test public void ソート_標準カラム_スプール開始時刻_降順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_START_TIME, TAG_SPOOL_START_TIME, 1, (o1, o2) -> compareNull(o2.getSpoolStartTime(), o1.getSpoolStartTime()); } @Test public void ソート_標準カラム_スプール終了時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_END_TIME, TAG_SPOOL_END_TIME, 0, (o1, o2) -> compareNull(o1.getSpoolEndTime(), o2.getSpoolEndTime()); } 2
  33. 33. @Test public void ソート_標準カラム_スプール終了時刻_降順() throws Exception { ソート(STANDARD_COLUMN, SPOOL_END_TIME, TAG_SPOOL_END_TIME, 1, (o1, o2) -> compareNull(o2.getSpoolEndTime(), o1.getSpoolEndTime()); } @Test public void ソート_標準カラム_印刷開始時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINT_START_TIME, TAG_PRINT_START_TIME, 0, (o1, o2) -> compareNull(o1.getPrintStartTime(), o2.getPrintStartTime()); } @Test public void ソート_標準カラム_印刷開始時刻_降順() throws Exception { (o1, o2) -> compareNull(o2.getPrintStartTime(), o1.getPrintStartTime()); } @Test public void ソート_標準カラム_印刷終了時刻_昇順() throws Exception { ソート(STANDARD_COLUMN, PRINT_END_TIME, TAG_PRINT_END_TIME, 0, (o1, o2) -> compareNull(o1.getPrintEndTime(), o2.getPrintEndTime()); } @Test public void ソート_標準カラム_印刷終了時刻_降順() throws Exception { ソート(STANDARD_COLUMN, PRINT_END_TIME, TAG_PRINT_END_TIME, 1, (o1, o2) -> compareNull(o2.getPrintEndTime(), o1.getPrintEndTime()); } @Test public void ソート_標準カラム_最終更新時刻_昇順() throws Exception { (o1, o2) -> compareNull(o1.getUpdateTime(), o2.getUpdateTime()); } @Test public void ソート_標準カラム_最終更新時刻_降順() throws Exception { ソート(STANDARD_COLUMN, UPDATE_TIME, TAG_UPDATE_TIME, 1, (o1, o2) -> compareNull(o2.getUpdateTime(), o1.getUpdateTime()); } 3
  34. 34. 22 テストケース 3 ページ 107 行
  35. 35. テストケース数 : 22 → 22 (100%) ページ数 : 6 → 3 (50%) 行数 : 247→107 (43%)
  36. 36. 嬉しい • ノイズの減少 • 本質的なコードだけが残る • 一覧性の向上 • たとえばテストがスペックに近 づく • 気がする
  37. 37. Q: ラムダ式は 何が 違うのか
  38. 38. A: 匿名関数が 簡略に書けて 嬉しい
  39. 39. それだけ?
  40. 40. そうだけど、 (全然むずかしくない) そうではない。 (文字数が減るとか、 それだけではない)
  41. 41. 開かれる 関数型スタイルへの道 • 私たちが愛する • 不変性 • 実装の隠蔽 • ドキュメントとしてのコード • 遅延評価 • 並列化
  42. 42. がもたらされる ことを他の人が 次回以降に説明 してくれます
  43. 43. 2. ラムダ式を 書く
  44. 44. 2. ラムダ式を書く • 何をラムダ式で書けるのか • どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  45. 45. 2. ラムダ式を書く • 何をラムダ式で書けるのか • どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  46. 46. Q : 何をラムダ式で 書けるのか
  47. 47. A : 関数型インタ フェースをラム ダ式で置き換え ることができる
  48. 48. 関数型インタフェース • 実装が必要なメソッドを一つだけ 持つインタフェース • 実装が必要なメソッド? → 未実装の abstract メソッド • 唯一の abstract メソッド以外に、 static メソッドや default メソッ ドが定義されている場合もある
  49. 49. 関数型インタフェースの例 • ~ JDK 7 • Runnable • Callable • Comparator • JDK 8 ~ • Predicate • Consumer • Supplier
  50. 50. 関数型インタフェースの例 • ~ JDK 7 • Runnable • Callable • Comparator • JDK 8 ~ • Predicate • Consumer • Supplier
  51. 51. JDK 7 までの Comparator public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
  52. 52. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  53. 53. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  54. 54. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  55. 55. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  56. 56. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  57. 57. JDK 8 の Comparator @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } ... (6 default methods) public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return Collections.reverseOrder(); } ... (8 static methods) }
  58. 58. @FunctionalInterface • 関数型インタフェースにつけるこ とができるアノテーション • つけなくてもよい • つけるとコンパイラが関数型イ ンタフェースかどうかチェック してくれる • 人間の目にもやさしい
  59. 59. デフォルトメソッド • インタフェースに実装を定義でき る記法 • default キーワードを記述 • 後方互換性を保ちながらインタ フェースを拡張するために導入 された • 詳細は次回……。
  60. 60. 2. ラムダ式を書く • 何をラムダ式で書けるのか • どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  61. 61. Q : どのように ラムダ式を 書けるのか
  62. 62. A : 次のように
  63. 63. ラムダ式の記法 • ( 実装するメソッドの引数 ) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2 }
  64. 64. ラムダ式の記法 • ( 実装するメソッドの引数 ) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2 }
  65. 65. ラムダ式の記法 • ( 実装するメソッドの引数 ) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  66. 66. ここから色々と 省略できる
  67. 67. ラムダ式の記法 (省略前) • ( 実装するメソッドの引数 ) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  68. 68. ラムダ式の記法 (省略 1) • 型推論 • 例 : Comparator の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  69. 69. ラムダ式の記法 (省略 1) • 型推論 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> { return o1 – o2; }
  70. 70. ラムダ式の記法 (省略 2) • 波括弧(「{}」)と return の省略 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> { return o1 – o2; }
  71. 71. ラムダ式の記法 (省略 2) • 波括弧(「{}」)と return の省略 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> o1 – o2
  72. 72. ラムダ式の記法 (省略 3) • 丸括弧(「()」)の省略 • 丸括弧が省略できるのは、メソッドの引数 が 1 つだけの場合
  73. 73. ラムダ式の記法 (省略 3) • 丸括弧(「()」)の省略前 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して (Integer t) -> { return (t > 100); }
  74. 74. ラムダ式の記法 (省略 3) • 丸括弧(「()」)の省略後 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して (Integer t) -> { return (t > 100); }
  75. 75. ラムダ式の記法 (省略 3) • 丸括弧(「()」)の省略後 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> { return (t > 100); }
  76. 76. ラムダ式の記法 (省略 3) • さらに省略すると • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> { return (t > 100); }
  77. 77. ラムダ式の記法 (省略 3) • さらに省略すると • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> t > 100
  78. 78. ラムダ式の記法 (引数なし) • メソッドに引数がない場合 丸括弧のみ記述する
  79. 79. ラムダ式の記法 (引数なし) • メソッドに引数がない場合 丸括弧のみ記述する • 例 : Callable<Integer> の場合 Integer call() に対して () -> { return 100; }
  80. 80. ラムダ式の記法 (引数なし) • メソッドに引数がない場合 丸括弧のみ記述する • 例 : Callable<Integer> の場合 Integer call() に対して () -> { return 100; }
  81. 81. ラムダ式の記法 (実質的に final) • 実質的に final • 匿名クラスでは、メソッド内で参照 するローカル変数には final キー ワードが必要 • ラムダ式では、その変数について final と同等に扱っていれば、final キーワードは不要
  82. 82. ラムダ式の記法 (this が表すもの) • http://www.atmarkit.co.jp/ait/ articles/1403/17/news105_2.h tml • (手抜きでスミマセン……)
  83. 83. 2. ラムダ式を書く • 何をラムダ式で書けるのか • どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  84. 84. Q : いつラムダ式を 書くべきか
  85. 85. A : 書けるところ ならどこでも
  86. 86. 書けるところなら どこでもラムダ式を書く • ラムダ式は関数型インタフェースの略 記法にすぎない • むずかしくない • こわくない • ラムダ式はノイズを減らして本質を残 す • 簡潔で読みやすいコードをつくる
  87. 87. と思っていますが、 プロダクション コードで色々と書 くにつれて合わな い場面が出てくる かもしれません
  88. 88. たとえば、ラムダ式の 意味をよく知っている (今のみなさん)にも かかわらず、なぜか読 みづらい、という場面 があるかも……?
  89. 89. そういうときは コードレビュー等 を通して適宜共有 していきましょう
  90. 90. 2. ラムダ式を書く • 何をラムダ式で書けるのか • どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  91. 91. ラムダ式さえ書かなくて もよいときもある • メソッド参照 • ざっくり言うとこう書ける仕組み • Before : name -> System.out.println(name) • After : System.out.println • のちほどもうちょっと説明します
  92. 92. 3. forEach による イテレーション
  93. 93. forEach による イテレーション • ラムダ式の活用例 • イテレーションが高級になっていく歴 史 • for (int i = 0; i < list.size(); i++) • for (String s : list) • list.forEach()
  94. 94. forEach による イテレーション • ラムダ式の活用例 • イテレーションが高級になっていく歴 史の第三段階 • for (int i = 0; i < list.size(); i++) • for (String s : list) • list.forEach()
  95. 95. 原始 for 文 final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (int i = 0; i < members.size(); i++) { System.out.println(members.get(i)); }
  96. 96. 原始 for 文 final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (int i = 0; i < members.size(); i++) { System.out.println(members.get(i)); } • ノイズが多い • OBOE や変数の取り違えが 起こりかねない
  97. 97. 拡張 for 文(Java 5~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (String member : members) { System.out.println(member); }
  98. 98. 拡張 for 文(Java 5~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (String member : members) { System.out.println(member); } • もう OBOE は起こらない • が、まだ冗長だ……。
  99. 99. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); Members.forEach(new Consumer<String>() { public void accept(final String name) { System.out.println(name); } });
  100. 100. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(new Consumer<String>() { public void accept(final String name) { System.out.println(name); } }); • ウッけっこうノイズが多いような ……
  101. 101. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(new Consumer<String>() { public void accept(final String name) { System.out.println(name); } }); • そんなときのためのラムダ式 • 1
  102. 102. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( (final String name) -> System.out.println(name)); • そんなときのためのラムダ式 • 1
  103. 103. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( (final String name) -> System.out.println(name)); • そんなときのためのラムダ式 • 2
  104. 104. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( name -> System.out.println(name)); • そんなときのためのラムダ式 • 2
  105. 105. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( name -> System.out.println(name)); • そんなときのためのラムダ式 • さえいらない(メソッド参照)
  106. 106. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(System.out.println); • そんなときのためのラムダ式 • さえいらない(メソッド参照)
  107. 107. forEach(Java 8~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(System.out.println); • そんなときのためのラムダ式 • さえいらない(メソッド参照) メンバーを それぞれ 標準出力に出す
  108. 108. メソッド参照 • http://www.atmarkit.co.jp/ait/ articles/1407/28/news023_3.h tml • (例によって手抜きでスミマセン ……)
  109. 109. まずは forEach の 例を紹介しましたが、 Stream API と組 み合わせるとこのラ ムダ式の簡潔さが大 活躍します
  110. 110. 次回以降を 乞うご期待
  111. 111. 白状すると
  112. 112. DataSpider の中 にこの forEach で 置き換えられる コードがなかなか 見つかりません
  113. 113. たとえばこれがい けるかな…… と思ったのですが
  114. 114. List<CellToWrite[]> rows = Arrays.asList(new CellToWrite[][] { new CellToWrite[neededColumnsCount] }); for (IntermediateCellData cell : data) { int row = cell.rowIndex - minRow; int column = cell.columnIndex - minColumn; rows.get(row)[column] = new CellToWrite( cell.address, cell.column, createWriteOption(cell)); }
  115. 115. List<CellToWrite[]> rows = Arrays.asList(new CellToWrite[][] { new CellToWrite[neededColumnsCount] }); data.forEach(cell -> { int row = cell.rowIndex - minRow; int column = cell.columnIndex - minColumn; rows.get(row)[column] = new CellToWrite( cell.address, cell.column, createWriteOption(cell)); }); • これだけだと 大して簡潔にならないし、しかも
  116. 116. List<CellToWrite[]> rows = Arrays.asList(new CellToWrite[][] { new CellToWrite[neededColumnsCount] }); data.forEach(cell -> { int row = cell.rowIndex - minRow; int column = cell.columnIndex - minColumn; rows.get(row)[column] = new CellToWrite( cell.address, cell.column, createWriteOption(cell)); }); • 言うほど読みやすくならない • ていうかコンパイルエラー処理されない例外の型 Exception
  117. 117. List<CellToWrite[]> rows = Arrays.asList(new CellToWrite[][] { new CellToWrite[neededColumnsCount] }); data.forEach(cell -> { int row = cell.rowIndex - minRow; int column = cell.columnIndex - minColumn; rows.get(row)[column] = new CellToWrite( cell.address, cell.column, createWriteOption(cell)); }); • 言うほど読みやすくならない • ていうかコンパイルエラー 処理されない例外の型 Exception Iterable#forEach(Consumer<? super T> action) @FunctionalInterface public interface Consumer<T> { void accept(T t); } public CellToWrite( String position, Column column, Excel2007WriteOption option) throws Exception {
  118. 118. List<CellToWrite[]> rows = Arrays.asList(new CellToWrite[][] { new CellToWrite[neededColumnsCount] }); data.forEach(cell -> { int row = cell.rowIndex - minRow; int column = cell.columnIndex - minColumn; try { rows.get(row)[column] = new CellToWrite( cell.address, cell.column, createWriteOption(cell)); } catch (Exception e) { throw new RuntimeException(e); } });
  119. 119. モサすぎる
  120. 120. (注意) これはラムダ式固有の問題というわけではなく、あ くまで forEach と関数型インタフェース周辺の問 題です。ただし、Stream API(と関数型インタ フェース)を使用する際にもこの問題は頻出すると 思われます
  121. 121. 関数型のコードと 親和性の高い設計 や API 設計に少し ずつ寄せていく努 力が必要になりそ うです
  122. 122. (XML Framework と Stream API との 可能性も含めた親 和性が気になると ころ……)
  123. 123. 次回以降が 楽しみです

×