Java8のStream API mapメソッドを理解するにはFunctionインタフェースを理解する

Java8のStream API mapメソッドを理解するにはFunctionインタフェースを理解する

Functionインタフェースを理解すればmapの動きが理解しやすいと思います。

java.util.function.Functionインタフェースは関数型インタフェースと呼ばれるインタフェースで、applyメソッド一つだけを持っています。

public interface Function<T, R> {
  R apply(T t); // T型の仮引数をR型に変換してreturnする

}

TとRを持ち、applyメソッドは仮引数にT,戻り値がRとなります。

Employeeクラスがあるとします。

public class Employee {
  private String name;
  private int age;

  public Employee(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
}

mapの引数はFunctionなので、匿名クラスを作成してみます。applyメソッドが返すのはここでは固定の文字列としています。TがEmployee型、RがString型です。

List<Employee> list = new ArrayList<Employee>();

list.add(new Employee("tanaka", 44));
list.add(new Employee("takahashi", 40));
list.add(new Employee("minami", 30));
list.add(new Employee("higashiguchi", 32));
list.add(new Employee("adachi", 200));
list.add(new Employee("rasubosu", 25));

List<String> str = list.stream().map(new Function<Employee, String>() {
  public String apply(Employee e) { // Employeeを仮引数に持ち、String型を返す
    return "xx"; // ここでは固定値としている
  }
}).collect(Collectors.toList());

上記からapplyメソッドは仮引数を変換処理したりして、別の型で返すことができることがわかります。

list変数はEmployeeインスタンスのリストですが、mapメソッドを使用することによって、Stream<String>(ここではList<String>にしている)に変換できていることがわかります。こういった変換処理をする場合にmapメソッドを使用します。

List<String> ret = list.stream().map(e -> e.toUpperCase()).collect(Collectors.toList());
ret.forEach(e -> System.out.println(e));

ちなみに関数型インタフェースは匿名クラスである必要はありません。以下のように定義することも可能です。

Function<Employee, String > func = new Function<Employee, String>() {
  public String apply(Employee e) {
    return "xx";
  }
};

ラムダ式で書く

ラムダ式で書くと以下のように記述できます。

Function<Employee, String > func = e -> e.getName().toUpperCase(); // ラムダ式
List<String> ret = list.stream().map(func).collect(Collectors.toList()); // mapメソッドの引数にfunc

このラムダ式は、Functionインタフェースがapplyメソッド一つしか持たない為、applyメソッドを呼んでいるのと同じ意味になります。メソッド名もreturnも{}も省略しているだけです。

// ラムダ式の実際のイメージ
public String apply(Employee e) {
  return e.getName().toUpperCase();
}

ここではapplyメソッドの仮引数はEmployeeで、戻り値がStringになっているので、eがEmployeeの仮引数、e.getName().toUpperCase()はString型です。

Java8のStream API filterメソッドを理解するにはPredicateインタフェースを理解する

コメント

タイトルとURLをコピーしました