「Javaを書いているけれどもJava屋とは言えない」私がよく使うStream APIの忘備録です。

Web系の実装で「DAOからSELECTしたリストを操作する」感じの処理が中心ですよ。

前提

テーブルをマッピングするValueObjectを用意します。

  • TCard.java
@Data
class TCard implements Serializable {
    private Integer userId;
    private Integer id;
    private Integer cardId;
    private Integer level;
    private Boolean isDeleted;
    :
}

所持カードを管理テーブルのイメージです。
メンバは、所有者であるユーザID、カードを識別するための連番、マスタIDなど。

変換

IDのリストを作る

WHERE INに与えるIDをまとめる場合など、よく使います。

public List<Integer> toIdList(List<TCard> cards) {
    return cards().stream()
        .map(e -> e.getId())
        .collect(Collectors.toList());
}

文字列として受け取ったリストをIntegerに変換する

HTML Formから受け取った文字列のリストを型変換するイメージです。

public List<Integer> toIntegerList(List<String> list) {
    return list.stream()
        .map(s -> NumberUtils.toInt(s))
      .collect(Collectors.toList());
}

IDがキーのHashMapをつくる

Listからハッシュマップに変換します。
複数データの突合を行うような場合に重宝します。

public Map<Integer, TCard> toHashMap(List<TCard> cards) {
    return cards.stream()
        .collect(Collectors.toMap(
            e -> e.getId(),
            e -> e
        ));
}

マッチ・検索

要素を1つ求める

public TCard findOne(List<TCard> cards, Integer searchId) {
    return cards.stream()
        .filter(s -> s.getId().equals(searchId))
        .findFirst()
        .get();
}

.findFirst().findAny()の違いがよくわかりません。。。

.findFirst()はOptionalが返ります。
上記のようにそのまま.get()するとNullPointerExceptionがスローされますのでダメですよ。

マッチする要素があるか調べる

public Boolean hasAny(List<TCard> cards, List<Integer> searchIdList) {
    return cards.stream()
        .anyMatch(s -> searchIdList.contains(s.getId()));
}

allMatch()もあり。

重複がないか調べる

「カードがすでに他のデッキにセットされているかどうか」のような処理で使います。

public Boolean hasNothing(List<TCard> cards, List<Integer> searchIdList) {
    return cards.stream()
        .noneMatch(s -> searchIdList.contains(s.getId()));
}

集計

ID別にカウント数る

所持カードから同じものをID別でカウントするイメージです。

public Map<Integer, Long> countById(List<TCard> cards) {
    return  cards.stream()
       .collect(Collectors.groupingBy(
            e -> e.getCardId(),
            Collectors.counting()
       ));

要素の値を合計する

リスト内の指定要素を合計します。
サンプルが強引なのはご容赦ください。。。

public Integer sum(List<TCard> cards) {
    return cards.stream()
        .mapToInt(s -> s.getLevel())
        .sum();
}

最大値を得る

public Integer getMaxLv(List<TCard> cards) {
    return cards.stream()
        .max( (l, r) -> Integer.compare(l.getLevel(), r.getLevel()) )
        .orElse(0);
}

終わりに

forEach()concat()など、他にも使いやすい機能がたくさんありますね。

誤りや、もっとシンプルな方法がありましたらぜひ教えてください。

この記事はtomita@atuwebがお届けしました。


参考

Java 8 Stream API にテキストを流してみた(終端操作編)
http://qiita.com/kumazo@github/items/284098c530fceb05805c

Java8 逆引き Stream API
http://qiita.com/nesheep5/items/da42df92397285d4ad0f

Java好き – Optional – nullを扱う新たな方法
http://www.javazuki.com/articles/javase/javase8-tutorial02.html



2016年05月26日:「mapToInt()」の使い方を誤っていたため、問題のある箇所をカットいたしました。

スポンサーリンク
ad_336
ad_336
  • このエントリーをはてなブックマークに追加
  • Evernoteに保存Evernoteに保存
スポンサーリンク
ad_336
コメントの入力は終了しました。