当サイトは、アフィリエイト広告を利用しています
java8のStreamAPIのmapメソッドの使いどころを
まとめていく。
javaで実装していてstreamを使う中ではfilterと並んで
よく使う。
また他のstreamAPIのメソッド(filterなど)と
組み合わせで使うことも多い
下記の本では streamAPI についても詳しく書いてありおススメです!
また当ブログで紹介しているjava8のstreamAPIを使った
コレクションや配列の操作方法を
下記記事でメソッド別にまとめています!
mapメソッドは配列またはlistの各要素に対して
指定した処理を実行できる中間操作メソッド
※中間操作であるため取り出すには終端操作をする必要がある。
簡単なサンプルを書いてみる
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {//数値のリストを作成List<Integer>sampleList = new ArrayList<>(Arrays.asList(1,2,3,4,5));sampleList.stream().forEach(val->System.out.print(val));//mapで加工処理をするsampleList = sampleList.stream().map(val->val+1).collect(Collectors.toList());System.out.println("");sampleList.stream().forEach(val->System.out.print(val));}}// 実行結果// 12345// 23456
mapメソッドを使ってリストの要素の数値にそれぞれ1を加算している。
とまぁ、上記サンプルを書いてみたが実際、プログラムを書くときに
あまり上記をようなパターン使うことはないので、自分がよく使うパターン
をまとめていく。
よく使うのか下記の3パターンが多い。
サンプルでは下記のオブジェクトクラスを使用する
public class Person {private final int id;private final String name;private final String address;private final int age;Person(int id,String name, String address,int age) {this.id = id;this.name = name;this.address = address;this.age = age;}public int getId() {return this.id;}public String getName() {return this.name;}public String getAddress() {return this.address;}public int getAge() {return this.age;}@Overridepublic String toString(){return "{" + this.id + " " + this.name + " " + this.address + " " + this.age +"}";}}
既存のlistでは後続の処理で、使いづらい時などは
先にmapメソッドを使って使い安いように加工した新しいlistを作る
ことはよくある。
単純に一つの属性のみを取り出してlistを作る
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<5;i++){Person pobj = new Person(i,"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}System.out.println("加工前");System.out.println(listBase);//mapで加工処理をするList<String>listEdit = listBase.stream().map(p->p.getName()).collect(Collectors.toList());System.out.println("加工後");System.out.println(listEdit);}}// 実行結果// 加工前// [{0 takashi0 東京0番地 10}, {1 takashi1 東京1番地 11}, {2 takashi2 東京2番地 12}, {3 takashi3 東京3番地 13}, {4 takashi4 東京4番地 14}]// 加工後// [takashi0, takashi1, takashi2, takashi3, takashi4]
nameだけのlistを作る。
実行サンプルを載せときます。
属性を取り出して加工することもできる。
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<5;i++){Person pobj = new Person(i,"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}System.out.println("加工前");System.out.println(listBase);//mapで加工処理をするList<String>listEdit = listBase.stream().map(p->p.getName() + p.getAddress()).collect(Collectors.toList());System.out.println("加工後");System.out.println(listEdit);}}// 実行結果// 加工前// [{0 takashi0 東京0番地 10}, {1 takashi1 東京1番地 11}, {2 takashi2 東京2番地 12}, {3 takashi3 東京3番地 13}, {4 takashi4 東京4番地 14}]// 加工後// [takashi0東京0番地, takashi1東京1番地, takashi2東京2番地, takashi3東京3番地, takashi4東京4番地]
nameとaddressを文字列結合した結果の要素を持つlistを作る
後述するマッチング処理とキーで突合せする前にに複合キーを作る時に
使ったりする
mapメソッドを使って別のオブジェクトに変換する。
コンボボックス用のオブジェクトのlistを作る時など使うことがある。
サンプルではPersonオブジェクトのlistを下記のComboオブジェクトのlistに変換する
public class Combo {private final String key;private final String value;Combo(String key, String value) {this.key = key;this.value = value;}public String getKey() {return this.key;}public String getValue() {return this.value;}@Overridepublic String toString(){return "{" + this.key + " " + this.value +"}";}}
mapメソッドで新しいオブジェクトのlistを作成する
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<5;i++){Person pobj = new Person(i,"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}System.out.println("Personオブジェクトのlist");System.out.println(listBase);//mapで別のオブジェクトリストに変換するList<Combo>listEdit = listBase.stream().map(p->{Combo con = new Combo(String.valueOf(p.getId()),p.getName());return con;}).collect(Collectors.toList());System.out.println("Comboオブジェクトのlist");System.out.println(listEdit);}}// 実行結果// Personオブジェクトのlist// [{0 takashi0 東京0番地 10}, {1 takashi1 東京1番地 11}, {2 takashi2 東京2番地 12}, {3 takashi3 東京3番地 13}, {4 takashi4 東京4番地 14}]// Comboオブジェクトのlist// [{0 takashi0}, {1 takashi1}, {2 takashi2}, {3 takashi3}, {4 takashi4}]
Personオブジェクトのlistからomboオブジェクトのlistを作成できている
サンプル実装をのせときます
用途としてはmapメソッドを使って、チェインする streamAPIの
などの処理を行えるようにする
reduceと組わせてみる
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<5;i++){Person pobj = new Person(i,"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}//mapメソッドでageのみのlistを作成List<Integer>ageList = listBase.stream().map(p->p.getAge()).collect(Collectors.toList());//reduceでageを合計するint result = ageList.stream().reduce(0, (accum,value)->accum + value);System.out.println(result);//1文で書くverint result2 = listBase.stream().map(p->p.getAge()).reduce(0, (accum,value)->accum + value);System.out.println(result2);}}// 実行結果// 60// 60
Personオブジェクトのままだとreduceが使えないので
reduceを使う前にmapメソッドで加工している。
サンプル実装をのせときます
reduceメソッドについては下記記事でまとめています。
次はsortedとの組み合わせをしてみる。
Person.javaを少し変更する
public class Person {private final String id;private final String name;private final String address;private final int age;Person(String id,String name, String address,int age) {this.id = id;this.name = name;this.address = address;this.age = age;}public String getId() {return this.id;}public String setId() {this.id = id;}public String getName() {return this.name;}public String getAddress() {return this.address;}public int getAge() {return this.age;}@Overridepublic String toString(){return "{" + this.id + " " + this.name + " " + this.address + " " + this.age +"}";}}
idの型をStringにする これでmapなしでsortedメソッドを使ってみると...
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<12;i++){Person pobj = new Person(String.valueOf(i),"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}//昇順でソートlistBase = listBase.stream().sorted(Comparator.comparing(Person::getId)).collect(Collectors.toList());listBase.stream().forEach(v->System.out.println(v));}}// 実行結果// {0 takashi0 東京0番地 10}// {1 takashi1 東京1番地 11}// {10 takashi10 東京10番地 20}// {11 takashi11 東京11番地 21}// {2 takashi2 東京2番地 12}// {3 takashi3 東京3番地 13}// {4 takashi4 東京4番地 14}// {5 takashi5 東京5番地 15}// {6 takashi6 東京6番地 16}// {7 takashi7 東京7番地 17}// {8 takashi8 東京8番地 18}// {9 takashi9 東京9番地 19}
idがStringであるためソートが狂ってしまう。
mapメソッドを使って
のどちらかをしてやることで正しくソートできる
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {// オブジェクトのListを生成List<Person>listBase = new ArrayList<>();for(int i=0;i<12;i++){Person pobj = new Person(String.valueOf(i),"takashi"+i,"東京"+ i + "番地",i + 10);listBase.add(pobj);}//mapメソッドでidをゼロ埋めしてからソートするlistBase = listBase.stream().map(p->{String zeroPaddingVal = String.format("%02d",Integer.parseInt(p.getId()));p.setId(zeroPaddingVal);return p;}).sorted(Comparator.comparing(Person::getId)).collect(Collectors.toList());listBase.stream().forEach(v->System.out.println(v));}}// 実行結果// {00 takashi0 東京0番地 10}// {01 takashi1 東京1番地 11}// {02 takashi2 東京2番地 12}// {03 takashi3 東京3番地 13}// {04 takashi4 東京4番地 14}// {05 takashi5 東京5番地 15}// {06 takashi6 東京6番地 16}// {07 takashi7 東京7番地 17}// {08 takashi8 東京8番地 18}// {09 takashi9 東京9番地 19}// {10 takashi10 東京10番地 20}// {11 takashi11 東京11番地 21}
サンプル実装をのせときます
sortedメソッドについては下記記事でまとめています。
mapメソッドをfilterメソッドと組み合わせることで
二つのlistのマッチング処理を実行することができる
詳しくは下記記事でまとめています!
java8のstreamAPIのmapメソッドの使いどころをサンプルを
使ってまとめてみた。
mapメソッドは単体で使うよりも他のstreamAIPのメソッドと組み合わせて
使うことでより便利になる。