Stream(Java8以降)の使い方

java8以降は、Streamを使えるようになった為、map,list等を使う際に、ラムダ式は少し理解が難しいですが、慣れるとStreamを使った方がフィルタをかけた処理や相互変換などが楽になりますので使っています。

※実際の業務レベルでは顧客の環境の問題で、あえて古いjavaバージョンにも対応していないといけないケースがよくありますので、このバージョン以降しか絶対に使えない処理というのは避けている現状もありますので、その辺を考慮して活用したいところです。

  • クラスの変換とListの生成

※1レコード単位のクラス⇒複数レコード単位のクラスにメンバをコピーし、さらにListを生成する処理です。またその際に、条件によるフィルタをかけて対象条件の情報のみ生成しています。

/**
1レコードの情報クラス(乗務員)
*/
public class Crew {

/** コード */
public int cd;

/** 名称 */
public String name;

/** 性別 */
public int sex;
}
/**
複数レコードの情報クラス(乗務員)
*/
public class CrewSum {

/** コード */
public int cd;
/** 名称 */
public String name;
/** 性別 */
public int sex;
/** その他項目 */
public String other;

/** 生成 */
public static CrewSum create(Crew crew) {
  CrewSum crewSum = new CrewSum();
  crewSum.cd = crew.cd;
  crewSum.name = crew.name;
  crewSum.sex = crew.sex;
  crewSum.other = "TEST";
  return crewSum;
}

public String getCd(){
return this.cd;
}

public String getName(){
return this.name;
}
}
// 1レコード単位のクラスを作成
List crewList = new ArrayList();

// 変換対象要素を追加
crewList.add(new Person(){{this.cd = 100;this.name = "太郎";this.sex = 1;}});
crewList.add(new Person(){{this.cd = 101;this.name = "花子";this.sex = 2;}});

// Streamを使ってリスト作成
List crewSumList = crewList.stream()
// フィルターによって性別が1:男のみでかつ、コードが100以上を対象とする
.filter(crew -> crew.sex == 1 && crew -> crew.cd >= 100)
// リスト全件にて生成メソッドを適用
.map(CrewSum::create)
// リストを集計生成
.collect(Collectors.toList());

// 作成したリストの繰り返し処理(ループ)
crewSumList.stream().forEach(data -> {
System.out.println("CrewSum : " + data.cd + ", " + data.name + ", " + data.sex + ", " + data.other);
});
  • Mapを作成する

上記のListをMapとして集計作成する場合は以下のような処理となります。準備処理までは同様です。

 
// Streamを使ってMap作成
List crewSumList = crewList.stream()
// フィルターによって性別が1:男のみでかつ、コードが100以上を対象とする
.filter(crew -> crew.sex == 1 && crew -> crew.cd >= 100)
// リスト全件にて生成メソッドを適用
.map(CrewSum::create)
// リストを名称で集約してMapを作成(KEYとなる)
. collect(Collectors.groupingBy(data -> data.name));

※上記のgroupingByを使ったMap化の場合、重複するキーがあった場合は、Listとして要素作成されます。重複時は、以下のような内容となります。

{"太郎": [{cd:100,name:"太郎", sex:1, other:"TEST"}, {cd:101,name:”太郎”, sex:1, other:”TEST” }]}

  • Listの要素の条件一致判定(一部一致)
List<String> list = new ArrayList<String>();

// 検索要素を追加する
list.add("AAA100");
list.add("AAA100");
list.add("AAA200");

// 一部の要素でも一致した場合はtrueを返却する。(この場合はtrue)
boolean match = list.stream().anyMatch( data -> data.contains("100"));

  • Listの要素の条件一致判定(完全一致)
List<String> list = new ArrayList<String>();

// 検索要素を追加する
list.add("AAA100");
list.add("AAA100");
list.add("AAA200");

// 全ての要素が一致した場合はtrueを返却する。(この場合はfalse)
boolean match = list.stream().allMatch( data -> data.contains("100"));

  • ソート(単一項目)

上記で作成したリストをソート(並び替え)します。

// コードで昇順の並び替えを行う。

// Comparatorを作成する。
Comparator<CrewSum> comp = Comparator.comparing(CrewSum::getCd);

// ソートする。
list.stream().sorted(comp).forEach(data -> {
System.out.println("CrewSum : " + data.getCd + ", " + data.getName);
});

  • ソート(複数項目)

上記で作成したリストを複数項目でソート(並び替え)します。複数項目の場合、thencomparingを使って、1項目目が同一の内容の場合に、2項目目以降をさらに比較を行うことができます。

また、reversed()をつける事で、降順にすることができます。

// コード(昇順)、名称(降順)の並び替えを行う。

// Comparatorを作成する。
Comparator<CrewSum> comp = Comparator.comparing(CrewSum::getCd).thenComparing(CrewSum::getName).reversed();

// ソートする。
list.stream().sorted(comp).forEach(data -> {
System.out.println("CrewSum : " + data.getCd + ", " + data.getName);
});