java8 lambdas chapter1_2
DESCRIPTION
Java8 lambdas chapter1_2TRANSCRIPT
Java8 Lambdas 勉強会 Chapter 1, 2
内藤 遥
Table of Contents
1. Introduction • Why Did They Need To Change Java Again ? • What Is Functional Programming ? • Example Domain
2. Lambda Expressions • Your First Lambda Expression • How to Spot a Lambda in a Haystack • Using Values • Functional Interfaces • Type Inference • Key Points
• マルチコア化で処理性能向上を目指す時代 • java.util.concurrent パッケージなどを使った並行処理には限界がある
⇒ ラムダ式を使った関数型プログラミングで簡潔、かつ強力な並行処理の実装が書ける
• 関数型言語の利点 • 可読性
• 保守性
• バグが少ない
Why Did They Need To Change Java Again ?
• 文字通り「関数」を使用したプログラミング • 入力した値に対して必ず同じ結果を返す
• オブジェクト指向におけるメソッド(一連の手続きをまとめて名前を付けたもの)とは異なる
• 関数の特徴 • 参照透過性
• ある関数に同じ入力値を与えれば、いつ評価しても必ず同じ値が得られる
• 変数は一度定義したら二度と変えない(再代入操作で状態を書き換えない)
• 第一級関数
• 変数に代入したり、別の関数の引数や戻り値になったりすることができる
What Is Functional Programming ?
Example Domain
• 本全体を通して、例の提示には共通の問題領域として音楽が使われる
• 要約は以下の通り
• アーティスト – 曲を作る個人やグループ
• トラック • 一つの曲
• アルバム • 複数のトラックの集合
• 音楽は関数型プログラミングの手法を説明する際に使われる
Your First Lambda Expression
• Swing(JavaのGUIライブラリ)でボタンをクリックした際の、匿名クラスを用いたevent listenerの実装
• 不要な行が多い
• 読みにくい
button.addActionListener(new ActionListerner() { public void actionPerformed(ActionEvent event) { System.out.println("button clicked"); } });
Your First Lambda Expression
• ラムダ式を使用
• (メソッドの引数) -> (処理) の形で書ける
• メソッド名や引数の型が省略できる
button.addActionListener(event -> System.out.println("button clicked"));
Your First Lambda Expression • ラムダ式を使った様々な実装例
Runnable noArguments = () -> System.out.println("Hello world"); ActionListener oneArgument = event -> System.out.println("button clicked"); Runnable multiStatement = () -> { System.out.println("Hello"); System.out.pringln(" World"); }; BinaryOperator<Long> add = (x,y) -> x + y; BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
Your First Lambda Expression • ラムダ式を使った様々な実装例
引数がないときは()のように書ける。戻り値の型はvoid
Runnable noArguments = () -> System.out.println("Hello world");
Your First Lambda Expression • ラムダ式を使った様々な実装例
引数が一つのときは左辺の()を省略できる。引数名は任意で指定可能
ActionListener oneArgument = event -> System.out.println("button clicked");
Your First Lambda Expression • ラムダ式を使った様々な実装例
処理が複数行に渡る場合は{}をつける
Runnable multiStatement = () -> { System.out.println("Hello"); System.out.pringln(" World"); };
Your First Lambda Expression • ラムダ式を使った様々な実装例
処理が一行の場合、returnを 省略できる(x + y の結果を返す処理の実装)
BinaryOperator<Long> add = (x,y) -> x + y;
Your First Lambda Expression • ラムダ式を使った様々な実装例
引数の型は省略せずにも書ける
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
Using Values
• 匿名クラスでは、finalのローカル変数、引数が扱える
• ラムダ式では、実質 finalのローカル変数、引数が扱える
• (場合によってはfinalが可読性を損なうこともあるため)
final String name = getUserName(); button.addActionListener(new ActionListerner(){ public void actionPerformed(ActionEvent event){ System.out.println("hi " + name); } });
String name = getUserName(); button.addActionListener(event -> System.out.println("hi " + name));
Using Values
• 下記の場合、 nameが実質finalでないのでコンパイルエラーとなる
String name = getUserName(); name = formatUserName(name); button.addActionListener(event -> System.out.println("hi " + name));
Functional Interfaces
• 関数型インターフェイスとは • 定義されている抽象メソッドが1つだけあるインターフェイス
• ラムダ式は、関数型インターフェイスに対して適用することができる
• 今後は、関数型インターフェイスをダイアグラムで表現する
• 関数に入っていく矢印は引数を、関数から出ていく矢印は戻り値の型を表す
• 関数型インターフェイスとダイアグラムの例は下記の通り
ActionListener
public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent event); }
ActionEvent
Functional Interfaces
• 関数型インターフェイスには、いくつかのコアグループがある
Interface name Arguments Returns Example
Predicate<T> T boolean Has this album been released yet?
Consumer<T> T void Printing out a value
Function<T, R> T R Get the name from an Artist Object
Supplier<T> None T A factory method
UnaryOperator<T> T T Logical not(!)
BinaryOperator<T> (T, T) T Multiplying two numbers(*)
Type Inference(型推論)
• Java7から、ダイヤモンド演算子を用いた型推論が可能
• メソッドの引数には型推論が使えなかったが、Java8から使えるようになった
Map<String, Integer> oldWordCounts = new HashMap<String, Integer>(); Map<String, Integer> diamondWordCounts = new HashMap<>();
useHashmap(new HashMap<>()); … private void useHashmap(Map<String, String> values);
Type Inference
• ラムダ式を使った型推論
• パラメータの型は省略可能
• javacで戻り値の型がbooleanであるかチェックしてくれる
Predicate<Integer> atLeast5 = x -> x > 5;
public interface Predicate<T> { boolean test(T t); }
Predicate T
boolean
Type Inference
• ラムダ式を使った型推論
• 後者では、型を指定していないため引数も戻り値の型も java.lang.Objectとして判別される -> 足し算ができないと怒られる
/* 正常に動く */ BinaryOperator<Long> addLongs = (x, y) -> x + y; /* コンパイルエラー */ BinaryOperator add = (x, y) -> x + y;
Key Points
• ラムダ式は、データであるかのように振る舞いを実装でき、メソッド名を省略できる
• ラムダ式は、以下のように書くことができる
• 関数型インターフェイスは定義されている抽象メソッドが1つだけあるインターフェイスのことで、ラムダ式は、関数型インターフェイスに対して適用することができる
BinaryOperator<Integer> add = (x, y) -> x + y;