Java 8 勉強会
第一回
ラムダ式 (1)
2015/3/2
開発部 3G 野口光太郎
ついに
Java 8
が使える
Java 8 導入予定
• Thunderbus
• 1.0 で導入済(8u31)
• PIMSYNC
• 2.2 で導入予定
• DataSpider Servista
• 4.0 で導入予定
Java 8 の新機能
• ラムダ式
• Stream API
• Date and Time API
• JavaFX 8
• etc…
Java 8 の新機能
• ラムダ式
• Stream API
• Date and Time API
• JavaFX 8
• etc…
ついに
ラムダ式
が使える
Java 8 勉強会
第一回
ラムダ式 (1)
2015/3/2
開発部 3G 野口光太郎
アジェンダ
1. ラムダ式は何が違うのか
2. ラムダ式を書く
3. forEach によるイテレーション
1.
ラムダ式は
何が
違うのか
ラムダ式とは
• 匿名関数の簡略な記法
• Java 8(2014/3)で導入
• 取り立てて新しい概念ではない
• C++11(2011 年)
• C# 3.0(2008 年)
• Lisp(ざっと 50 年くらい前)
ラムダ式とは
• 匿名関数の簡略な記法
• Java 8(2014/3)で導入
• 取り立てて新しい概念ではない
• C++11(2011 年)
• C# 3.0(2008 年)
• Lisp(ざっと 50 年くらい前)
匿名関数の
簡略な記法
……?
匿名関数とは
• 匿名の関数
• 要するにこれのこと
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;
}
});
匿名関数の簡略な記法
• こう書ける
List numbers = Arrays.asList(1, 1, 2, 3, 5);
Collections.sort(numbers, (i1, i2) -> i2 - i1);
で?
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());
}
}
);
}
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());
}
}
);
}
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
テストの内容にとっては全部どうでもいい
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());
}
}
);
}
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 アダプタのテスト
コードの例(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)
(匿名関数)
• こう書ける
• メソッドに関数を直接渡せる
(注意)
実際に過去に書いたコードの中からノイズが減って
嬉しい例としてたまたまこれを思い出したので挙げ
ましたが、関数型のスタイルという観点では、そも
そもあまり長いラムダ式は推奨されない、という考
え方もあるようです。
あとそもそもアサーションの仕方がダサいとかは今
はツッコまない方向で……。
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();
}
});
}
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
@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
@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
@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
@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
@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
22 テストケース
6 ページ
247 行
• こう書ける
@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
@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
@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
22 テストケース
3 ページ
107 行
テストケース数 :
22 → 22 (100%)
ページ数 :
6 → 3 (50%)
行数 :
247→107 (43%)
嬉しい
• ノイズの減少
• 本質的なコードだけが残る
• 一覧性の向上
• たとえばテストがスペックに近
づく
• 気がする
Q:
ラムダ式は
何が
違うのか
A:
匿名関数が
簡略に書けて
嬉しい
それだけ?
そうだけど、
(全然むずかしくない)
そうではない。
(文字数が減るとか、
それだけではない)
開かれる
関数型スタイルへの道
• 私たちが愛する
• 不変性
• 実装の隠蔽
• ドキュメントとしてのコード
• 遅延評価
• 並列化
がもたらされる
ことを他の人が
次回以降に説明
してくれます
2.
ラムダ式を
書く
2. ラムダ式を書く
• 何をラムダ式で書けるのか
• どのようにラムダ式を書けるのか
• いつラムダ式を書くべきか
• ラムダ式さえ書かなくてもよいと
きもある
2. ラムダ式を書く
• 何をラムダ式で書けるのか
• どのようにラムダ式を書けるのか
• いつラムダ式を書くべきか
• ラムダ式さえ書かなくてもよいと
きもある
Q :
何をラムダ式で
書けるのか
A :
関数型インタ
フェースをラム
ダ式で置き換え
ることができる
関数型インタフェース
• 実装が必要なメソッドを一つだけ
持つインタフェース
• 実装が必要なメソッド?
→ 未実装の abstract メソッド
• 唯一の abstract メソッド以外に、
static メソッドや default メソッ
ドが定義されている場合もある
関数型インタフェースの例
• ~ JDK 7
• Runnable
• Callable
• Comparator
• JDK 8 ~
• Predicate
• Consumer
• Supplier
関数型インタフェースの例
• ~ JDK 7
• Runnable
• Callable
• Comparator
• JDK 8 ~
• Predicate
• Consumer
• Supplier
JDK 7 までの Comparator
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
@FunctionalInterface
• 関数型インタフェースにつけるこ
とができるアノテーション
• つけなくてもよい
• つけるとコンパイラが関数型イ
ンタフェースかどうかチェック
してくれる
• 人間の目にもやさしい
デフォルトメソッド
• インタフェースに実装を定義でき
る記法
• default キーワードを記述
• 後方互換性を保ちながらインタ
フェースを拡張するために導入
された
• 詳細は次回……。
2. ラムダ式を書く
• 何をラムダ式で書けるのか
• どのようにラムダ式を書けるのか
• いつラムダ式を書くべきか
• ラムダ式さえ書かなくてもよいと
きもある
Q :
どのように
ラムダ式を
書けるのか
A :
次のように
ラムダ式の記法
• ( 実装するメソッドの引数 ) -> { 処理 }
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(Integer o1, Integer o2) -> { return o1 – o2 }
ラムダ式の記法
• ( 実装するメソッドの引数 ) -> { 処理 }
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(Integer o1, Integer o2) -> { return o1 – o2 }
ラムダ式の記法
• ( 実装するメソッドの引数 ) -> { 処理 }
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(Integer o1, Integer o2) -> { return o1 – o2; }
ここから色々と
省略できる
ラムダ式の記法 (省略前)
• ( 実装するメソッドの引数 ) -> { 処理 }
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(Integer o1, Integer o2) -> { return o1 – o2; }
ラムダ式の記法 (省略 1)
• 型推論
• 例 : Comparator の場合
int compare(Integer o1, Integer o2)
に対して
(Integer o1, Integer o2) -> { return o1 – o2; }
ラムダ式の記法 (省略 1)
• 型推論
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(o1, o2) -> { return o1 – o2; }
ラムダ式の記法 (省略 2)
• 波括弧(「{}」)と return の省略
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(o1, o2) -> { return o1 – o2; }
ラムダ式の記法 (省略 2)
• 波括弧(「{}」)と return の省略
• 例 : Comparator<Integer> の場合
int compare(Integer o1, Integer o2)
に対して
(o1, o2) -> o1 – o2
ラムダ式の記法 (省略 3)
• 丸括弧(「()」)の省略
• 丸括弧が省略できるのは、メソッドの引数
が 1 つだけの場合
ラムダ式の記法 (省略 3)
• 丸括弧(「()」)の省略前
• 例 : Predicate<Integer> の場合
boolean test(Integer t)
に対して
(Integer t) -> { return (t > 100); }
ラムダ式の記法 (省略 3)
• 丸括弧(「()」)の省略後
• 例 : Predicate<Integer> の場合
boolean test(Integer t)
に対して
(Integer t) -> { return (t > 100); }
ラムダ式の記法 (省略 3)
• 丸括弧(「()」)の省略後
• 例 : Predicate<Integer> の場合
boolean test(Integer t)
に対して
t -> { return (t > 100); }
ラムダ式の記法 (省略 3)
• さらに省略すると
• 例 : Predicate<Integer> の場合
boolean test(Integer t)
に対して
t -> { return (t > 100); }
ラムダ式の記法 (省略 3)
• さらに省略すると
• 例 : Predicate<Integer> の場合
boolean test(Integer t)
に対して
t -> t > 100
ラムダ式の記法 (引数なし)
• メソッドに引数がない場合
丸括弧のみ記述する
ラムダ式の記法 (引数なし)
• メソッドに引数がない場合
丸括弧のみ記述する
• 例 : Callable<Integer> の場合
Integer call()
に対して
() -> { return 100; }
ラムダ式の記法 (引数なし)
• メソッドに引数がない場合
丸括弧のみ記述する
• 例 : Callable<Integer> の場合
Integer call()
に対して
() -> { return 100; }
ラムダ式の記法
(実質的に final)
• 実質的に final
• 匿名クラスでは、メソッド内で参照
するローカル変数には final キー
ワードが必要
• ラムダ式では、その変数について
final と同等に扱っていれば、final
キーワードは不要
ラムダ式の記法
(this が表すもの)
• http://www.atmarkit.co.jp/ait/
articles/1403/17/news105_2.h
tml
• (手抜きでスミマセン……)
2. ラムダ式を書く
• 何をラムダ式で書けるのか
• どのようにラムダ式を書けるのか
• いつラムダ式を書くべきか
• ラムダ式さえ書かなくてもよいと
きもある
Q :
いつラムダ式を
書くべきか
A :
書けるところ
ならどこでも
書けるところなら
どこでもラムダ式を書く
• ラムダ式は関数型インタフェースの略
記法にすぎない
• むずかしくない
• こわくない
• ラムダ式はノイズを減らして本質を残
す
• 簡潔で読みやすいコードをつくる
と思っていますが、
プロダクション
コードで色々と書
くにつれて合わな
い場面が出てくる
かもしれません
たとえば、ラムダ式の
意味をよく知っている
(今のみなさん)にも
かかわらず、なぜか読
みづらい、という場面
があるかも……?
そういうときは
コードレビュー等
を通して適宜共有
していきましょう
2. ラムダ式を書く
• 何をラムダ式で書けるのか
• どのようにラムダ式を書けるのか
• いつラムダ式を書くべきか
• ラムダ式さえ書かなくてもよいと
きもある
ラムダ式さえ書かなくて
もよいときもある
• メソッド参照
• ざっくり言うとこう書ける仕組み
• Before :
name -> System.out.println(name)
• After :
System.out.println
• のちほどもうちょっと説明します
3.
forEach による
イテレーション
forEach による
イテレーション
• ラムダ式の活用例
• イテレーションが高級になっていく歴
史
• for (int i = 0; i < list.size(); i++)
• for (String s : list)
• list.forEach()
forEach による
イテレーション
• ラムダ式の活用例
• イテレーションが高級になっていく歴
史の第三段階
• for (int i = 0; i < list.size(); i++)
• for (String s : list)
• list.forEach()
原始 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));
}
原始 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 や変数の取り違えが
起こりかねない
拡張 for 文(Java 5~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
for (String member : members) {
System.out.println(member);
}
拡張 for 文(Java 5~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
for (String member : members) {
System.out.println(member);
}
• もう OBOE は起こらない
• が、まだ冗長だ……。
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);
}
});
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);
}
});
• ウッけっこうノイズが多いような
……
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
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
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
forEach(Java 8~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
members.forEach(
name -> System.out.println(name));
• そんなときのためのラムダ式
• 2
forEach(Java 8~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
members.forEach(
name -> System.out.println(name));
• そんなときのためのラムダ式
• さえいらない(メソッド参照)
forEach(Java 8~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
members.forEach(System.out.println);
• そんなときのためのラムダ式
• さえいらない(メソッド参照)
forEach(Java 8~)
final List<String> members =
Arrays.asList(“Ohshima”, “Hirose”, “Nancii”,
“Tanaka”, “Chen”, “Takano”);
members.forEach(System.out.println);
• そんなときのためのラムダ式
• さえいらない(メソッド参照)
メンバーを それぞれ 標準出力に出す
メソッド参照
• http://www.atmarkit.co.jp/ait/
articles/1407/28/news023_3.h
tml
• (例によって手抜きでスミマセン
……)
まずは forEach の
例を紹介しましたが、
Stream API と組
み合わせるとこのラ
ムダ式の簡潔さが大
活躍します
次回以降を
乞うご期待
白状すると
DataSpider の中
にこの forEach で
置き換えられる
コードがなかなか
見つかりません
たとえばこれがい
けるかな……
と思ったのですが
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));
}
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));
});
• これだけだと
大して簡潔にならないし、しかも
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
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 {
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);
}
});
モサすぎる
(注意)
これはラムダ式固有の問題というわけではなく、あ
くまで forEach と関数型インタフェース周辺の問
題です。ただし、Stream API(と関数型インタ
フェース)を使用する際にもこの問題は頻出すると
思われます
関数型のコードと
親和性の高い設計
や API 設計に少し
ずつ寄せていく努
力が必要になりそ
うです
(XML
Framework と
Stream API との
可能性も含めた親
和性が気になると
ころ……)
次回以降が
楽しみです

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

  • 1.
    Java 8 勉強会 第一回 ラムダ式(1) 2015/3/2 開発部 3G 野口光太郎
  • 3.
  • 4.
    Java 8 導入予定 •Thunderbus • 1.0 で導入済(8u31) • PIMSYNC • 2.2 で導入予定 • DataSpider Servista • 4.0 で導入予定
  • 5.
    Java 8 の新機能 •ラムダ式 • Stream API • Date and Time API • JavaFX 8 • etc…
  • 6.
    Java 8 の新機能 •ラムダ式 • Stream API • Date and Time API • JavaFX 8 • etc…
  • 7.
  • 8.
    Java 8 勉強会 第一回 ラムダ式(1) 2015/3/2 開発部 3G 野口光太郎
  • 9.
  • 10.
  • 11.
    ラムダ式とは • 匿名関数の簡略な記法 • Java8(2014/3)で導入 • 取り立てて新しい概念ではない • C++11(2011 年) • C# 3.0(2008 年) • Lisp(ざっと 50 年くらい前)
  • 12.
    ラムダ式とは • 匿名関数の簡略な記法 • Java8(2014/3)で導入 • 取り立てて新しい概念ではない • C++11(2011 年) • C# 3.0(2008 年) • Lisp(ざっと 50 年くらい前)
  • 13.
  • 14.
    匿名関数とは • 匿名の関数 • 要するにこれのこと 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; } });
  • 15.
    匿名関数の簡略な記法 • こう書ける List numbers= Arrays.asList(1, 1, 2, 3, 5); Collections.sort(numbers, (i1, i2) -> i2 - i1);
  • 16.
  • 17.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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()); } } ); }
  • 19.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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 テストの内容にとっては全部どうでもいい
  • 20.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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()); } } ); }
  • 21.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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()); } } ); } • こう書ける
  • 22.
    Excel アダプタのテスト コードの例(Before) • こういうのも privateinterface 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) (匿名関数) • こう書ける • メソッドに関数を直接渡せる
  • 23.
  • 24.
    xxx アダプタのテスト コードの例(Before) • こういうのも @Testpublic 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(); } }); }
  • 25.
    xxx アダプタのテスト コードの例(Before) • こういうのも @Testpublic 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
  • 26.
    @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
  • 27.
    @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
  • 28.
    @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
  • 29.
    @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
  • 30.
    @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
  • 31.
  • 32.
    • こう書ける @Test publicvoid ソート_標準カラム_文書管理番号_昇順() 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
  • 33.
    @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
  • 34.
    @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
  • 35.
  • 36.
    テストケース数 : 22 →22 (100%) ページ数 : 6 → 3 (50%) 行数 : 247→107 (43%)
  • 37.
    嬉しい • ノイズの減少 • 本質的なコードだけが残る •一覧性の向上 • たとえばテストがスペックに近 づく • 気がする
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
    開かれる 関数型スタイルへの道 • 私たちが愛する • 不変性 •実装の隠蔽 • ドキュメントとしてのコード • 遅延評価 • 並列化
  • 43.
  • 44.
  • 45.
    2. ラムダ式を書く • 何をラムダ式で書けるのか •どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  • 46.
    2. ラムダ式を書く • 何をラムダ式で書けるのか •どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  • 47.
  • 48.
  • 49.
    関数型インタフェース • 実装が必要なメソッドを一つだけ 持つインタフェース • 実装が必要なメソッド? →未実装の abstract メソッド • 唯一の abstract メソッド以外に、 static メソッドや default メソッ ドが定義されている場合もある
  • 50.
    関数型インタフェースの例 • ~ JDK7 • Runnable • Callable • Comparator • JDK 8 ~ • Predicate • Consumer • Supplier
  • 51.
    関数型インタフェースの例 • ~ JDK7 • Runnable • Callable • Comparator • JDK 8 ~ • Predicate • Consumer • Supplier
  • 52.
    JDK 7 までのComparator public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
  • 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.
    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.
    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.
    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.
    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.
    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) }
  • 59.
    @FunctionalInterface • 関数型インタフェースにつけるこ とができるアノテーション • つけなくてもよい •つけるとコンパイラが関数型イ ンタフェースかどうかチェック してくれる • 人間の目にもやさしい
  • 60.
    デフォルトメソッド • インタフェースに実装を定義でき る記法 • defaultキーワードを記述 • 後方互換性を保ちながらインタ フェースを拡張するために導入 された • 詳細は次回……。
  • 61.
    2. ラムダ式を書く • 何をラムダ式で書けるのか •どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  • 62.
  • 63.
  • 64.
    ラムダ式の記法 • ( 実装するメソッドの引数) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2 }
  • 65.
    ラムダ式の記法 • ( 実装するメソッドの引数) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2 }
  • 66.
    ラムダ式の記法 • ( 実装するメソッドの引数) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  • 67.
  • 68.
    ラムダ式の記法 (省略前) • (実装するメソッドの引数 ) -> { 処理 } • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  • 69.
    ラムダ式の記法 (省略 1) •型推論 • 例 : Comparator の場合 int compare(Integer o1, Integer o2) に対して (Integer o1, Integer o2) -> { return o1 – o2; }
  • 70.
    ラムダ式の記法 (省略 1) •型推論 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> { return o1 – o2; }
  • 71.
    ラムダ式の記法 (省略 2) •波括弧(「{}」)と return の省略 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> { return o1 – o2; }
  • 72.
    ラムダ式の記法 (省略 2) •波括弧(「{}」)と return の省略 • 例 : Comparator<Integer> の場合 int compare(Integer o1, Integer o2) に対して (o1, o2) -> o1 – o2
  • 73.
    ラムダ式の記法 (省略 3) •丸括弧(「()」)の省略 • 丸括弧が省略できるのは、メソッドの引数 が 1 つだけの場合
  • 74.
    ラムダ式の記法 (省略 3) •丸括弧(「()」)の省略前 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して (Integer t) -> { return (t > 100); }
  • 75.
    ラムダ式の記法 (省略 3) •丸括弧(「()」)の省略後 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して (Integer t) -> { return (t > 100); }
  • 76.
    ラムダ式の記法 (省略 3) •丸括弧(「()」)の省略後 • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> { return (t > 100); }
  • 77.
    ラムダ式の記法 (省略 3) •さらに省略すると • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> { return (t > 100); }
  • 78.
    ラムダ式の記法 (省略 3) •さらに省略すると • 例 : Predicate<Integer> の場合 boolean test(Integer t) に対して t -> t > 100
  • 79.
  • 80.
    ラムダ式の記法 (引数なし) • メソッドに引数がない場合 丸括弧のみ記述する •例 : Callable<Integer> の場合 Integer call() に対して () -> { return 100; }
  • 81.
    ラムダ式の記法 (引数なし) • メソッドに引数がない場合 丸括弧のみ記述する •例 : Callable<Integer> の場合 Integer call() に対して () -> { return 100; }
  • 82.
    ラムダ式の記法 (実質的に final) • 実質的にfinal • 匿名クラスでは、メソッド内で参照 するローカル変数には final キー ワードが必要 • ラムダ式では、その変数について final と同等に扱っていれば、final キーワードは不要
  • 83.
  • 84.
    2. ラムダ式を書く • 何をラムダ式で書けるのか •どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  • 85.
  • 86.
  • 87.
    書けるところなら どこでもラムダ式を書く • ラムダ式は関数型インタフェースの略 記法にすぎない • むずかしくない •こわくない • ラムダ式はノイズを減らして本質を残 す • 簡潔で読みやすいコードをつくる
  • 88.
  • 89.
  • 90.
  • 91.
    2. ラムダ式を書く • 何をラムダ式で書けるのか •どのようにラムダ式を書けるのか • いつラムダ式を書くべきか • ラムダ式さえ書かなくてもよいと きもある
  • 92.
    ラムダ式さえ書かなくて もよいときもある • メソッド参照 • ざっくり言うとこう書ける仕組み •Before : name -> System.out.println(name) • After : System.out.println • のちほどもうちょっと説明します
  • 93.
  • 94.
    forEach による イテレーション • ラムダ式の活用例 •イテレーションが高級になっていく歴 史 • for (int i = 0; i < list.size(); i++) • for (String s : list) • list.forEach()
  • 95.
    forEach による イテレーション • ラムダ式の活用例 •イテレーションが高級になっていく歴 史の第三段階 • for (int i = 0; i < list.size(); i++) • for (String s : list) • list.forEach()
  • 96.
    原始 for 文 finalList<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (int i = 0; i < members.size(); i++) { System.out.println(members.get(i)); }
  • 97.
    原始 for 文 finalList<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 や変数の取り違えが 起こりかねない
  • 98.
    拡張 for 文(Java5~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (String member : members) { System.out.println(member); }
  • 99.
    拡張 for 文(Java5~) final List<String> members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); for (String member : members) { System.out.println(member); } • もう OBOE は起こらない • が、まだ冗長だ……。
  • 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.
    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); } }); • ウッけっこうノイズが多いような ……
  • 102.
    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
  • 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)); • そんなときのためのラムダ式 • 1
  • 104.
    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
  • 105.
    forEach(Java 8~) final List<String>members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( name -> System.out.println(name)); • そんなときのためのラムダ式 • 2
  • 106.
    forEach(Java 8~) final List<String>members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach( name -> System.out.println(name)); • そんなときのためのラムダ式 • さえいらない(メソッド参照)
  • 107.
    forEach(Java 8~) final List<String>members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(System.out.println); • そんなときのためのラムダ式 • さえいらない(メソッド参照)
  • 108.
    forEach(Java 8~) final List<String>members = Arrays.asList(“Ohshima”, “Hirose”, “Nancii”, “Tanaka”, “Chen”, “Takano”); members.forEach(System.out.println); • そんなときのためのラムダ式 • さえいらない(メソッド参照) メンバーを それぞれ 標準出力に出す
  • 109.
  • 110.
    まずは forEach の 例を紹介しましたが、 StreamAPI と組 み合わせるとこのラ ムダ式の簡潔さが大 活躍します
  • 111.
  • 112.
  • 113.
    DataSpider の中 にこの forEachで 置き換えられる コードがなかなか 見つかりません
  • 114.
  • 115.
    List<CellToWrite[]> rows = Arrays.asList(newCellToWrite[][] { 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)); }
  • 116.
    List<CellToWrite[]> rows = Arrays.asList(newCellToWrite[][] { 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)); }); • これだけだと 大して簡潔にならないし、しかも
  • 117.
    List<CellToWrite[]> rows = Arrays.asList(newCellToWrite[][] { 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
  • 118.
    List<CellToWrite[]> rows = Arrays.asList(newCellToWrite[][] { 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 {
  • 119.
    List<CellToWrite[]> rows = Arrays.asList(newCellToWrite[][] { 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); } });
  • 120.
  • 121.
  • 122.
  • 123.
    (XML Framework と Stream APIとの 可能性も含めた親 和性が気になると ころ……)
  • 124.