コレクション操作を簡易に記述できる
参考:@IT:ラムダ式で本領を発揮する関数型インターフェースとStream APIの基礎知識
//--- 基本 -------------------------------------------------
@Test
//forEach リスト内容を表示する
public void testForEach() throws Exception {
users.forEach(user -> System.out.println(user.name())); //それぞれ処理する
}
//--- 変換 -------------------------------------------------
@Test
//map 社員名リストに変換する
public void testMap() throws Exception {
final List<String> names = users
//stream化する
.stream()
//map 要素すべてになんらかの処理をしてその結果から新しいリストを作成する
.map(user -> user.name())
//メソッド参照 .map(User::name) でも可
.collect(Collectors.toList()); //まとめる
//内容出力 .forEach(System.out::println) でも可
names.forEach(user -> System.out.println(user));
}
//--- フィルタ -------------------------------------------------
@Test
//filter 特定部署の所属者を抽出する
public void testFilter() throws Exception {
users.stream()
//条件で抽出する
.filter(user -> user.branch().startsWith("情報システム部"))
//内容出力
.forEach(user -> System.out.println(user.name()));
}
//--- ユニーク/ソート -------------------------------------------------
@Test
//distinct 部署一覧
public void testDistinct() throws Exception {
users.stream()
//部署リストに変換
.map(user -> user.branch())
//ユニークを取る
.distinct()
//部署名でソート
.sorted()
//内容出力
.forEach(System.out::println);
}
@Test
//sort 特定部署の所属者を抽出する
public void testSort() throws Exception {
users.stream()
//条件抽出
.filter(user -> user.branch().startsWith("情報システム部"))
//ソート
.sorted((x, y) -> x.branch().compareTo(y.branch()))
//Comparatorのユーティリティメソッド使えば簡単
//.sorted(Comparator.comparing(User::branch))
//内容出力
.forEach(user -> System.out.println(user.name() + ":" + user.branch()));
}
// --- 有無確認 ------------------------------
@Test
//optional 写真URL未設定のユーザの存在有無
public void testOptional() throws Exception {
final Optional<User> noUrlUser = users.stream()
//写真URLが未設定のユーザを抽出
.filter(user -> isEmpty(user.photoUrl()))
//1件目を返却
.findFirst();
//Optionalで返却されるので、isPresent()関数で有無確認可能(仮に存在しなくてもnull返却されない)
//Optional:nullの可能性がある値をラップして、より安全なプログラムが書けるようにする仕組み
if (noUrlUser.isPresent()) {
System.out.println("There is no url user.");
}
}
@Test
//anyMatch 写真URL未設定のユーザの存在有無(もっと簡単に書ける)
public void testAnyMatch() throws Exception {
//コレクション自体に存在チェック関数が用意された anyMatch, allMatch, noneMatch
if(users.stream().anyMatch(user -> isEmpty(user.photoUrl()))){
System.out.println("There is no url user.");
}
}
// --- 応用編 -------------------------------
@Test
//groupingBy 部門所属ユーザ数
public void testGrouping() throws Exception {
users.stream()
//groupingBy 部門をキーとしたMapを返す Map<String, List<User>>
.collect(Collectors.groupingBy(User::branch))
//Setコレクションを返す Set<Entry<String, List<Usre>>>
.entrySet()
//改めてストリーム化
.stream()
//部門名でソート
.sorted((x, y) -> x.getKey().compareTo(y.getKey()))
//部門名と所属者数を出力
.forEach(x -> System.out.println(x.getKey() + ":" + x.getValue().size()));
}
@Test
//Predicate 部門抽出条件を引数で渡す
public void testPredicate() throws Exception {
filterByFunction(user -> user.branch().startsWith("情報システム部"));
}
private void filterByFunction(Predicate<? super User> predicate) {
users.stream()
//条件抽出(filterは引数Predicate<T>を取る)
.filter(predicate)
//ソート
.sorted(Comparator.comparing(User::branch))
//内容出力
.forEach(user -> System.out.println(user.name() + ":" + user.branch()));
}
参考:http://www.atmarkit.co.jp/ait/articles/1404/30/news017.html#012
リスト操作が簡易になり、コード中にさらりとフィルタ処理など記述できるようになるが、コントローラ、モデル中などで直接リスト操作を記述しないこと。
述語やポリシーは特定のクラスにDRYで記述されていなければならない。
今後もリストラッパークラスを用意し、その中でStreamAPIを利用すること。当社の実装で言えば、LambdaJコード部分をStreamAPIに置き換える。