JSR 335
Project Lambda
     開発部
     てるー
Java8 (JSR 337)
JSR 308: Annotations on Java Types

JSR 310: Date and Time API

JSR TBD: More Small Enhancements to the Java
Programming Language

JSR 335: Lambda Expressions for the Java Programming
Language

JSR TBD: Java Platform Module System
例1       Before
File srcDir = new File(“src");

File[] javaFiles = srcDir.listFiles(new FilenameFilter() {
       @Override
       public boolean accept(File dir, String name) {
         return name.endsWith(".java");
       }
   });
例1       After
File srcDir = new File(“src");

File[] javaFiles = srcDir.listFiles(
     (dir, name) -> name.endsWith(".java"));
例2        Before
static final List<Integer> NUMBER_LIST =
        Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

List<Integer> evenNumberList =
         new ArrayList<Integer>();
for (int number : NUMBER_LIST) {
  if (number % 2 == 0) {
      evenNumberList.add(number);
  }
}
例2        After
static final List<Integer> NUMBER_LIST =
        Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

List<Integer> evenNumberList =
       new ArrayList<Integer>(NUMBER_LIST);
evenNumberList.retainAll(i -> i % 2 == 0);
アジェンダ
1. どういうときにラムダ式が使えるの?
2. ラムダ式の形式は?
3. ラムダ式の中で final じゃないローカル変数
   を扱える!?
4. ラムダ式を書かないでメソッドを参照させ
   る!
5. インターフェースにも実装が!?
6. java.lang.Iterable がなんかヤバい!
1. どういうときにラムダ
    式が使えるの?
ラムダ式が使える型について
•   新たに関数型という型が追加される訳では
    ない

•   ラムダ式は単一メソッドのインターフェー
    スのインスタンスを簡単に書ける記法

• 単一メソッドのインターフェース
=> Functional interface
つまり、こういうことだ
File[] javaFiles = srcDir.listFiles(new FilenameFilter() {
       @Override
       public boolean accept(File dir, String name) {
         return name.endsWith(".java");
       }
   });
                            =
FilenameFilter filter =
     (dir, name) -> name.endsWith(".java");
File[] javaFiles = srcDir.listFiles(filter);
例1    メソッドが1つ
interface Runnable {
   void run();
}
例2 java.lang.Object の public で実
装されているものはカウントしない
interface Comparator<T> {
   int compare(T o1, T o2);
   boolean equals(Object obj);
}
例3    同じシグネチャ

interface X {
   int method(String s);
}

interface Y {
   int method(String s);
}

interface Z extends X, Y {}
例4 default method はカウントしな
い
public interface Block<T> {
  void apply(T t);

    Block<T> chain(Block<? super T> second) default {
      return Blocks.chain(this, second);
    }
}
標準ライブラリの Functional interface
•   java.lang.Runnable
•   java.util.concurrent.Callable
•   java.security.PrivilegedAction
•   java.util.Comparator
•   java.io.FileFilter
•   java.nio.file.PathMatcher
•   java.lang.reflect.InvocationHandler
•   java.beans.PropertyChangeListener
•   java.awt.event.ActionListener
•   javax.swing.event.ChangeListener
java.util.functions のインターフェー
ス
•   BiBlock             •   Factory
•   BiMapper            •   IntBinaryOperator
•   BinaryOperator      •   IntMapper
•   BiPredicate         •   LongBinaryOperato
•   Block                   r
•   DoubleBinaryOpera   •   LongMapper
    tor                 •   Mapper
•   DoubleMapper        •   Predicate
2. ラムダ式の形式は?
ラムダ式の形式
LambdaParameters '->' LambdaBody
LambdaParameters
// 引数なし
() -> { return 0; }

// 引数が 1 つ
(int x) -> { return 0; }
(x) -> { return 0; }
x -> { return 0; }

// 引数が複数
(int x, int y) -> { return 0; }
(x, y) -> { return 0; }
LambdaBody
// 何もしない
() -> { }

// 単文
(x, y) -> { return x + y; }
(x, y) -> x + y

// 複文
() -> {
   System.out.println("test");
   return 0;
}
3. ラムダ式の中で final
じゃないローカル変数を
     扱える!?
外部のローカル変数には final をつけ
る
File srcDir = new File("src");
final String suffix = ".java";

File[] javaFiles = srcDir.listFiles(new FilenameFilter() {
       @Override
       boolean accept(File dir, String name) {
         return name.endsWith(suffix);
       }
   });
ラムダ式の場合は final をつけていな
くても OK!
File srcDir = new File("src");
String suffix = ".java";

File[] javaFiles = srcDir.listFiles(
     (dir, name) -> name.endsWith(suffix));
ただし、実質的に final じゃないとダ
メ!
File srcDir = new File("src");
String suffix = ".java";
suffix = ".xml";

File[] javaFiles = srcDir.listFiles(
     (dir, name) -> name.endsWith(suffix)); // コンパイルエ
ラー
ただし、実質的に final じゃないとダ
メ!
File srcDir = new File("src");
String suffix = ".java";

File[] javaFiles = srcDir.listFiles(
     (dir, name) -> {
           suffix = ".xml"; // コンパイルエラー
           return name.endsWith(suffix);}); // コンパイルエラー
実験タイム
4. ラムダ式を書かないで
メソッドを参照させる!
Method references
•   ラムダ式を書く代わりに既存のメソッドを
    呼び出すことができる
•   形式
    o   <クラス名 or インスタンス名> :: <メソッド名 or
        new>
•   例
    o System::getProperty
    o "abc"::length
    o String::length
    o ArrayList::new
例1    static メソッド
class Person {
  private final String name;
  private final int age;

    public static int compareByAge(Person a, Person b) { ... }
    public static int compareByName(Person a, Person b)
{ ... }
}

Person[] people = ...
Arrays.sort(people, Person::compareByAge);
例2 インスタンスメソッド(1)
    (<インスタンス名>::<メソッド名>)
class ComparisonProvider {
  public int compareByAge(Person a, Person b) { ... }
  public int compareByName(Person a, Person b) { ... }
}

ComparisonProvider comparisonProvider =
    new ComparisonProvider();
Arrays.sort(
    people,
    comparisonProvider ::compareByName);
例3 インスタンスメソッド(2)
 (<クラス名>::<メソッド名>)
String[] names = new String[] {"Hoge", "Piyo", "Boo"};
Arrays.sort(names, String::compareToIgnoreCase);




class String {
  public int compareToIgnoreCase(String str)
}

interface Comparator<T> {
   int compare(T o1, T o2);
}
例4        コンストラクタ
class Car { ... }

interface CarFactory {
   Car newCar();
}

CarFactory factory = Car::new;
5. インターフェースにも
     実装が?
Default methods
インターフェースのメソッドにデフォルトの処
理を書ける

public interface Comparator<T> {
  ...
  Comparator<T> reverse() default {
      return Collections.reverseOrder(this);
  }
  ...
}
どうしてこのような仕様があるのか?
•   前バージョンで公開済みのインターフェー
    スに新たなメソッドを追加しても、互換性
    を保てる
•   新たなメソッドが追加されたインター
    フェース
    o java.util.Comparator
        compose
        reverse
    o java.lang.Iterable
        filter
        forEach
継承について
•   クラスの実装の方がインターフェースのデ
    フォルトよりも優先される

•   複数のインターフェースを継承していた場
    合
    o   コンフリクトした場合、どちらの default method を
        使用するかを記述する必要がある
    o   ただし、継承元のインターフェースの親が同じだっ
        た場合は特別
どちらの default method を使用する
かを記述する場合
interface A {
   void method() default { ... }
}

interface B {
   void method() default { ... }
}

interface TestInterface extends A, B {
   void method() default {
     B.super.method();
   }
}
オーバライドした方が優先される
interface Base {
   void method() default { ... }
}

interface A extends Base {
   void method() default { ... }
}

interface B extends Base { }

interface TestInterface extends A, B {
   void method(); // A の default method になる
}
6. java.lang.Iterable が
      なんかヤバい
java.lang.Iterable の新メソッド
•   allMatch   •   groupBy
•   anyMatch   •   groupByMulti
•   count      •   into
•   cumulate   •   isEmpty
•   fillter    •   map
•   flatMap    •   mapped
•   forEach    •   mapReduce
•   getAny     •   noneMatch
•   getFirst   •   reduce
•   getOnly    •   sorted
               •   uniqueElements
java.lang.Iterable の新メソッド
•   allMatch   •   groupBy
•   anyMatch   •   groupByMulti
•   count      •   into
•   cumulate   •   isEmpty
•   fillter    •   map
•   flatMap    •   mapped
•   forEach    •   mapReduce
•   getAny     •   noneMatch
•   getFirst   •   reduce
•   getOnly    •   sorted
               •   uniqueElements
リストの中から偶数のみを
標準出力する(1)
•   forEach
    o   [概要]: 個々の要素へ処理を加える
    o   [引数]: Block<? super T>
    o   [戻り値]: なし
    o   [Block の抽象メソッド]: void apply(T t)
リストの中から偶数のみを
標準出力する(2)
•   filter
    o   [概要]: 条件にあった要素だけをフィルタリングする
    o   [引数]: Predicate<? super T>
    o   [戻り値]: Iterable<T>
    o   [Predicate の抽象メソッド]: boolean test(T t)
リストの中から偶数のみを
 標準出力する(3)
static final List<Integer> NUMBER_LIST =
     Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);



Iterable<Integer> evenNumberList =
     NUMBER_LIST.filter(i -> i % 2 == 0);
evenNumberList .forEach(i -> System.out.println(i));
リストの中から偶数のみを
 標準出力する(4)
static final List<Integer> NUMBER_LIST =
     Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);



NUMBER_LIST.filter(i -> i % 2 == 0)
           .forEach(i -> System.out.println(i));
リストの中の身長の最大値を出力する
(1)
•   map
    o [概要]: 要素に処理を加えることで、新しいコレク
      ションを生成する
    o [引数]: Mapper<? super T,? extends U>
    o [戻り値]: Iterable<U>
    o [Mapper の抽象メソッド]: U map(T t)
リストの中の身長の最大値を出力する
(2)
•   reduce
    o [概要]: 要素をまとめて、1つの値を生成する
    o [引数1]:結果の初期値
    o [引数2]: BinaryOperator<T>
    o [戻り値]: 最終的な結果
    o [BinaryOperator の抽象メソッド]: T eval(T left,T
      right)
リストの中の身長の最大値を出力する
(3)
class Student {
    private final String name;
    private final int height;
    ...
}
static final List<Student> STUDENT_LIST;
...

Iterable<Integer> heightList =
     STUDENT_LIST.map(s -> s.getHeight());
int max = heightList.reduce(-1, (x, y) -> Math.max(x, y));
System.out.println(max);
リストの中の身長の最大値を出力する
(4)
class Student {
    private final String name;
    private final int height;
    ...
}
static final List<Student> STUDENT_LIST;
...

System.out.println(
    STUDENT_LIST.map(s -> s.getHeight())
                  .reduce(-1, (x, y) -> Math.max(x, y)));
参考資料
・公式ドキュメント
http://openjdk.java.net/projects/lambda/
・JDK ダウンロード
http://jdk8.java.net/lambda/
・Eclipse で Java8 !
http://d.hatena.ne.jp/tm_senda/20120715/1342378068
・Project Lambda ハンズオン
http://javainthebox.net/lambdahandson.html
・bitter_foxの日記
http://d.hatena.ne.jp/bitter_fox/

Project lambda