SlideShare uma empresa Scribd logo
1 de 59
Baixar para ler offline
Java SE 8 的 Lambda 連鎖效應
 - 語法、風格與程式庫
林信良
   http://openhome.cc
caterpillar@openhome.cc
議程
• 一級函式與 λ 演算
• JDK8 的 Lambda 語法
• 介面預設方法(Default method)
• 擴充的 Collection 框架
• 函數式風格的可能性
一級函式與 λ 演算




             第十一個希臘字母
             物理上的波長符號
             放射學的衰變常數
             線性代數的特徵值
             λ 演算
             ….
一級值
• 值(Value)可指定給變數
• 一級(First-class)值可傳給函式或從函式中傳回
                物件

                     函式?



      基本型態           運算式?
一級函式
• 有些語言中函式是一等公民(First-class citizen)
 – 高階函式(High order function)

              function doSome(param) {
                  // 作些事
              }

              var doSome = function(param) {
                  // 作些事
              };
一級函式
• 有些語言中函式是一等公民(First-class citizen)
 – 高階函式(High order function)

               function doSome(param) {
                   // 作些事
               }

               var doSome = function(param) {
                   // 作些事
               };


        doOther(function(param) {
                 function(param)
            // 作些事 // 作些事
        });      };
一級函式
• 有些語言中函式是一等公民(First-class citizen)
 – 高階函式(High order function)

                function doSome(param) {
                    // 作些事
                }

                var doSome = function(param) {
                    // 作些事
                };

      function doAction(opt) {
          return function(param) {
              // 作些事 作些事
                     //
          };     };
      };
What is


           http://en.wikipedia.org/wiki/Lambda
           In programming languages such as
           Lisp and Python, lambda is an
           operator used to denote
           anonymous functions or closures




/lambda/
λ 演算(Lambda calculus)
• 每個表達式(Expression)代表具單一參數函數
• 參數本身亦可接受具有單一參數的函式
• f(x) = x * 2 可匿名地表示為 …

        λ x. x * 2
        x -> x * 2
λ 演算(Lambda calculus)
• 如果要套用 x 為 2
  (x -> x * 2)(2)
  = 2 * 2
  = 4
• g(y) = y -1 代入 f(x) 匿名地表達為…
  (y -> y - 1)(x -> x * 2)
  = x -> x * 2 - 1
λ 演算(Lambda calculus)
• 多參數的函數可使用單參數函數套用而成
 (x, y) -> x * x + y * y
 = x -> (y -> x * x + y * y)

•若x為2而y為3
(x -> (y -> x * x + y * y))(2)(3)
= (y -> 2 * 2 + y * y)(3)
= 4 + 3 * 3
= 4 + 9
= 13
λ 演算(Lambda calculus)
• 可用來表現任何可計算函數
• 可使用函數實現控制結構(如 if、forEach等)
• 一個小型通用語言
  butThat = cond->fv->tv->
         (cond or fv) and (cond and tv)

  butThat(true)(10)(20)
   = (true or 10) and (true and 20)
   = true and 20
   = 20
一級函式與 λ 演算
• 不同語言提供不同程度的 Lambda 表達式支援
(x -> x * 2)(2)


             function(x) {
                 return x * 2;
             }(2);
一級函式與 λ 演算
• JDK8 前存在 Lambda 語法類似品
 – 匿名內部類別(Anonymous inner class)

• 定義單一抽象方法(Single abstract method)介
面模擬一級函式

 interface Func<P, R> {
     R apply(P p);
 }
一級函式與 λ 演算
• 使用匿名內部類別來表示 x         -> x * 2
new Func<Integer, Integer>() {
    public Integer apply(Integer x) {
        return x * 2;
    }
};
一級函式與 λ 演算
• 設計 compose(f, g)        達成 g(f(x)) 的函數組合
static <A, B, C> Func<A, C> compose(
            final Func<A, B> f, final Func<B, C> g) {
    return new Func<A, C>() {
                public C apply(A x) {
                    return g.apply(f.apply(x));
                }
           };
}
一級函式與 λ 演算
• f(x) = x + 2 而 g(y) = y * 3
• h(x) = g(f(x))
compose(
    new Func<Integer, Integer>() {
        public Integer apply(Integer x) {
            return x + 2;
        }
    },
    new Func<Integer, Integer>() {
        public Integer apply(Integer y) {
            return y * 3;
        }
    }
);
JDK8 的 Lambda 語法




        λ
JDK8 的 Lambda 語法
  • 使用 JDK8 的 Lambda 語法來表示 x                   -> x * 2
    (Integer x) -> x + 2


  • 設計 compose(f,          g) 達成 g(f(x)) 的函數組合
static <A, B, C> Func<A, C> compose(Func<A, B> f, Func<B, C> g) {
    // 忽略.apply 就是 x -> g(f(x))
    return x -> g.apply(f.apply(x));
}

  • f(x) = x + 2 、 g(y) = y * 3、h(x) = g(f(x))
   compose((Integer x) -> x + 2, (Integer y) -> y * 3)
JDK8 的 Lambda 表示式
•   (type parameter) -> function_body

    – 單一運算式
      (int x, int y) -> x + y

      () -> 42


    – 陳述區塊
      (String s) -> { System.out.println(s); }
函式介面(Functional interface)
• 單一抽象方法的介面
 public interface Runnable {
     void run();
 }
 public interface Comparator<T> {
     int compare(T o1, T o2);
 }

 public interface Callable<V> {
     V call() throws Exception
 }
目標定型(Target typing)
• 目標型態與環境(Context)有關
 – 目標型態可用於類型推斷(Type inference)
Runnable r = () -> { out.println("later"); };
Comparator<String> c = (s1, s2) -> s1.compareTo(s2);
Collections.sort(lists, (s1, s2) -> -s1.compareTo(s2));



• 獨立於型態的Lambda 表示式
Callable<String> c = () -> "done";
PrivilegedAction<String> a = () -> "done";
不只是語法蜜糖
• 語彙範圍(Lexical scoping)
    – Lambda 語法本體中的名稱與包裹環境相同
public class Hello {
  Runnable r1 = () -> { out.println(this); }
  Runnable r2 = () -> { out.println(toString()); }

    public String toString() { return "Hello, world!"; }

    public static void main(String... args) {
      new Hello().r1.run();
      new Hello().r2.run();
    }
}
不只是語法蜜糖
• 變數捕捉(Variable capture)
 – 與 final 等效的區域變數不需要 final
Callable<String> helloCallable(String name) {
  String hello = "Hello";
  return () -> (hello + ", " + name);
}

• 編譯錯誤...
int sum = 0;
list.forEach(e -> { sum += e.size(); });

• 建議...
int sum = list.map(e -> e.size())
              .reduce(0, (a, b) -> a + b);
方法參考(Method reference)
 • 類別靜態方法
public class Person {
  ...
  public static int compareByAge(Person a, Person b) { ... }
  public static int compareByName(Person a, Person b) { ... }
}

Person[] people = ...
// Arrays.sort(people, (a, b) -> a.getAge() – b.getAge());
Arrays.sort(people, Person::compareByAge);

interface Block<T> { void run(T arg); }
Block<Integer> b1 = System::exit;   // void   exit(int status)
Block<String[]> b2 = Arrays::sort; // void    sort(Object[] a)
Block<String> b3 = MyProgram::main; // void   main(String... args)
Runnable r = MyProgram::main;       // void   main(String... args)
方法參考(Method reference)
• 特定物件實例方法
public class ComparisonProvider {
    public int compareByName(Person p1, Person p2) { ... }
    public int compareByAge(Person p1, Person p2) { ... }
}
...
ComparisonProvider comparisonProvider = ...;
Arrays.sort(people, comparisonProvider::compareByName);



• 實例方法中可帶物件狀態
  – 相當於讓 Lambda 語法帶有狀態(Closure 的替代?)
方法參考(Method reference)
• 任意類別的實例方法
List<String> names = Arrays.asList("Justin", ...);

Collections.sort(names,
                (s1, s2) -> s1.compareToIgnoreCase(s2));

Collections.sort(names, String::compareToIgnoreCase);
方法參考(Method reference)
• 讓 Lambda 語法的目標類型可以變換
Callable<String> c = () -> "done";
PrivilegedAction<String> a = c::call;
建構式參考(Constructor reference)
• 像是特殊的靜態方法參考:
 SocketFactory factory = SocketImpl::new;
介面預設方法(Default method)
介面預設方法(Default method)
• JDK8 前實作介面以實現多個規格的繼承來源
  – 捨棄繼承多個實作來源的可能性,規避了多重繼承下實
    作衝突等問題
public class Ball implements Comparable<Ball> {
  public boolean notEquals(Ball that) {
     return this.radius - that.radius;
  }
  // 底下都是根據notEquals()實作
  public boolean lessThan(Ball that) {
     return this.notEquals(that) < 0;
  }
  public boolean lessOrEquals(Ball that) {
     return this.lessThan(that) || this.notEquals(that) == 0;
  }
  public boolean greaterThan(Ball that) {
     return !this.lessOrEquals(that);
  } ...
介面預設方法(Default method)
• JDK8 介面可以是根據抽象的共用實作
public interface Comparable<T> {
  boolean notEquals(T that);

  boolean lessThan(T that) default {
     return this.notEquals(that) < 0;
  }
  boolean lessOrEquals(T that) default {
     return this.lessThan(that) || this.notEquals(that) == 0;
  }
  boolean greaterThan(T that) default {
     return !this.lessOrEquals(that);
  } ...
介面預設方法(Default method)
• JDK8 可以實作具有預設方法的介面
public class Ball implements Comparable<Ball> {
  public boolean notEquals(Ball that) {
     return this.radius - that.radius;
  } ...

• 實作可能發生衝突..
 interface Robot implements Artist, Gun {
   void draw() default { Artist.super.draw(); }
 }
介面預設方法(Default method)
• 擴充既有程式庫以搭配 Lambda 語法
 – 僅在介面中新增方法定義?
 – 使用靜態方法?像是 Collections.filter(…)?
 – 獨立的新 API?像是 Collection2 框架?
 interface Iterator<E> {
   boolean hasNext();
   E next();
   void remove();

     void skip(int i) default {
       for (; i > 0 && hasNext(); i--) next();
     }
 }
擴充的 Collection 框架
• 高階函式
 – 可讀性
 – 簡潔性
 – 導入新的抽象層

• 以迭代為例…
 for(Ball b : balls) {
     b.setColor(RED);
 }

 balls.forEach(b -> { b.setColor(RED); });
擴充的 Collection 框架
• 匿名類別作不到嗎?
– 想分離關切點,但又帶入新的關切點
 balls.forEach(new Block<Ball> {
     public void apply(Ball ball) {
         ball.setColor(RED);
     }
 });



• 傳入 Lambda 表示式,而非傳入不想要的雜訊
擴充的 Collection 框架
• 為什麼是 Collection 框架?
• 許多問題都是資料處理問題…
 – 關聯式資料通常就是待處理資料群集…

• filter、map、fold 等是處理資料時的高階抽象
 –   過濾一組資料
 –   將一組資料對應至另一組資料
 –   逐一取得資料計算單一結果
 –   …
擴充的 Collection 框架
• 管線化(Piped)操作
int sum = names.filter(s -> s.length() < 3)
               .map(s -> s.length())
               .reduce(0, (sum, len) -> sum + len);


int sum = names.filter(s -> s.length() < 3)
               .map(s -> s.length())
               .sum();
擴充的 Collection 框架
• 管線化(Piped)操作
blocks.filter(b -> b.getColor() == BLUE)
      .forEach(b -> { b.setColor(RED); });


List<Block> blue = blocks.filter(b -> b.getColor() == BLUE)
                         .into(new ArrayList<>());


Set<Box> blueBlock = blocks.filter(b -> b.getColor() == BLUE)
                           .map(b -> b.getContainingBox())
                           .into(new HashSet<>());
擴充的 Collection 框架
• 延遲(Laziness)
 int sum = blocks.filter(b -> b.getColor() == BLUE)
                 .map(b -> b.getWeight())
                 .sum();



• 捷徑(short-circuiting)
 Block firstBlue = blocks.filter(b -> b.getColor() == BLUE)
                         .getFirst();
擴充的 Collection 框架
• 共用的函式介面(java.util.functions)
 – Predicate
   – boolean test(T t)
 – Block
   – void apply(T t);
 – Mapper
   – U map(T t)
 – ...
擴充的 Collection 框架
• 已實作 filter、map 與 fold 的細節
 –   循序?
 –   遞迴?
 –   共用資料結構?
 –   平行化?

• 可以用更高階的抽象來處理資料
 int sum = blocks.parallel()
                 .filter(b -> b.getColor() == BLUE)
                 .map(b -> b.getWeight())
                 .sum();
全部放在一起
for (Method m : enclosingInfo.getEnclosingClass().getDeclaredMethods()) {
     if (m.getName().equals(enclosingInfo.getName()) ) {
         Class<?>[] candidateParamClasses = m.getParameterTypes();
         if (candidateParamClasses.length == parameterClasses.length) {
             boolean matches = true;
             for(int i = 0; i < candidateParamClasses.length; i++) {
                 if (!candidateParamClasses[i].equals(parameterClasses[i])) {
                     matches = false;
                     break;
                 }
             }

             if (matches) { // finally, check return type
                 if (m.getReturnType().equals(returnType) )
                     return m;
             }
         }
    }
}

throw new InternalError("Enclosing method not found");
全部放在一起
Method matching =
  Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
  .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
  .filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
  .filter(m -> Objects.equals(m.getReturnType(), returnType))
  .getFirst();

if (matching == null)
    throw new InternalError("Enclosing method not found");
return matching;
全部放在一起
List<Album> favs = new ArrayList<>();
for (Album a : albums) {
    boolean hasFavorite = false;
    for (Track t : a.tracks) {
        if (t.rating >= 4) {
            hasFavorite = true;
            break;
        }
    }
    if (hasFavorite)
        favs.add(a);
}

Collections.sort(favs, new Comparator<Album>() {
                           public int compare(Album a1, Album a2) {
                                return a1.name.compareTo(a2.name);
                           }});
全部放在一起
List<Album> sortedFavs =
  albums.filter(a -> a.tracks.anyMatch(t -> (t.rating >= 4)))
        .sortedBy(a -> a.name)
        .into(new ArrayList<>());
函數式風格的可能性
函數式風格的可能性
• Lambda 語法在原語言中提供小型通用語言
• 在某些問題領域…
 – 提供以 λ 演算解題的可能性

• Java 在函數式程式設計(Functional
Parogramming)的可能性?
函數式風格的可能性
• 費式數的定義
 { F0 = 0, F1 = 1, Fn = Fn-1 + Fn-2 }


• 指令式程式設計(Imperative programming)?
 int fib(int n) {
     int a = 1; int b = 1;
     for(int i = 2; i < n; i++) {
         int tmp = b; b = a + b; a = tmp;
     }
     return b;
 }
函數式風格的可能性
• 函數式程式設計?
 int fib(int n) {
     if(n == 0 || n == 1) return n;
     else return fib(n - 1) + fib(n - 2);
 }


• 使用 Haskell
 fib 0 = 0
 fib 1 = 1
 fib n = fib (n-1) + fib (n-2)
函數式風格的可能性
• 函數式語言的特徵               fib 0 = 0
                         fib 1 = 1
–   一級函式                 fib n = fib (n-1) + fib (n-2)
–   Immutable            sum [] = 0
–   Lazy evaluation      sum (x:xs) = x + sum xs
–   Pattern match
                         {2 * x | x ∈ {1, 2..100}}
–   List comprehension
                         [2 * x | x <- [1, 2..100]]
–   Curried function
                         f x y = x + y
                         g y = f 1 y
函數式風格的可能性
• JDK8 有多少函數式風格的特性?
– 直接支援 Lambda 語法
– 使用 final 變數強制 Immutable
– 以 API 封裝複雜細節達到…
  – 延遲求值
  – 模式匹配
  – List comprehension
  – Partially applied 與 Curried function
函數式風格的可能性
 • 以 API 封裝複雜細節,留下函數式外觀給使用者
   – Functional Java(functionaljava.org)
     – 目的就是為了讓 Java 實現函數式風格
     – 主要針對 JDK5 以上
     – 使用匿名內部類別繼承抽象類別
  final Array<String> a = array("Hello", "There", "what");
  final boolean b = a.exists(new F<String, Boolean>() {
      public Boolean f(final String s) {
          return fromString(s).forall(isLowerCase);
      }
  });

boolean b = a.exists(s -> fromString(s).forall(isLowerCase));
函數式風格的可能性
• 以 API 封裝複雜細節,留下函數式外觀給使用者
– Guava(code.google.com/p/guava-libraries)
  – 主要目的並非為了讓 Java 實現函數式風格
  – 主要針對 JDK5 以上
  – 使用匿名內部類別實作介面
函數式風格的可能性
 • Guava 目前不鼓勵函數式風格
Multiset<Integer> lengths = HashMultiset.create(
  FluentIterable.from(strings)
    .filter(new Predicate<String>() {
        public boolean apply(String string) {
          return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
        }
     })
    .transform(new Function<String, Integer>() {
        public Integer apply(String string) {
          return string.length();
        }
     }));

Multiset<Integer> lengths = HashMultiset.create(
  FluentIterable.from(strings)
    .filter(s -> CharMatcher.JAVA_UPPER_CASE.matchesAllOf(s))
    .transform(s -> s.length())
));
總結
• λ 語法為 Java 提供了小型通用語言,在某些問題
領域,提供 λ 演算解題的可能性
• 除 JDK 程式庫將搭配 λ 語法演化,開放原始碼如
Functional Java、Guava 等也將呈現不同風格
• 新的抽象層將平行化、函數式等實作予以封裝,
簡潔的表述能力,使開發者進一步思索 map、
filter、fold 等問題的基本形式
參考資料
•   State of the Lambda v4
    – http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html

•   State of the Lambda: Libraries Edition
    – http://cr.openjdk.java.net/~briangoetz/lambda/collections-
       overview.html

•   Project Lambda
    – http://openjdk.java.net/projects/lambda/

•   Lambda calculus
    – http://en.wikipedia.org/wiki/Lambda_calculus

•   Functional Programming for Java Developers
    – http://shop.oreilly.com/product/0636920021667.do

•   APIO讲稿——函数式编程
    – http://www.byvoid.com/blog/apio-fp/
感謝 Orz
林信良
http://openhome.cc
caterpillar@openhome.cc

Mais conteúdo relacionado

Mais procurados

Introduction to Basic Haskell Components (In Chinese)
Introduction to Basic Haskell Components (In Chinese)Introduction to Basic Haskell Components (In Chinese)
Introduction to Basic Haskell Components (In Chinese)ChengHui Weng
 
Java8 lambda
Java8 lambdaJava8 lambda
Java8 lambdakoji lin
 
Ecmascript
EcmascriptEcmascript
Ecmascriptjay li
 
Javascript share
Javascript shareJavascript share
Javascript shareXu Mac
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试lydiafly
 
Use Lambdas in Android
Use Lambdas in AndroidUse Lambdas in Android
Use Lambdas in Androidkoji lin
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascriptjay li
 
Haskell Foundations
Haskell FoundationsHaskell Foundations
Haskell Foundationsguestf8c45d
 
Java SE 8 技術手冊第 10 章 - 輸入輸出
Java SE 8 技術手冊第 10 章 - 輸入輸出Java SE 8 技術手冊第 10 章 - 輸入輸出
Java SE 8 技術手冊第 10 章 - 輸入輸出Justin Lin
 
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Justin Lin
 
深入淺出 Web 容器 - Tomcat 原始碼分析
深入淺出 Web 容器  - Tomcat 原始碼分析深入淺出 Web 容器  - Tomcat 原始碼分析
深入淺出 Web 容器 - Tomcat 原始碼分析Justin Lin
 
Java SE 8 技術手冊第 15 章 - 通用API
Java SE 8 技術手冊第 15 章 - 通用APIJava SE 8 技術手冊第 15 章 - 通用API
Java SE 8 技術手冊第 15 章 - 通用APIJustin Lin
 
Introduction to C++ over CLI
Introduction to C++ over CLIIntroduction to C++ over CLI
Introduction to C++ over CLI建興 王
 
3, operators
3, operators3, operators
3, operatorsted-xu
 
Clojure简介与应用
Clojure简介与应用Clojure简介与应用
Clojure简介与应用Robert Hao
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanupted-xu
 
ES5 introduction
ES5 introductionES5 introduction
ES5 introductionotakustay
 
OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)Kai-Feng Chou
 

Mais procurados (20)

Introduction to Basic Haskell Components (In Chinese)
Introduction to Basic Haskell Components (In Chinese)Introduction to Basic Haskell Components (In Chinese)
Introduction to Basic Haskell Components (In Chinese)
 
Java8 lambda
Java8 lambdaJava8 lambda
Java8 lambda
 
Ecmascript
EcmascriptEcmascript
Ecmascript
 
Execution
ExecutionExecution
Execution
 
Javascript share
Javascript shareJavascript share
Javascript share
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
 
Hi Haskell
Hi HaskellHi Haskell
Hi Haskell
 
Use Lambdas in Android
Use Lambdas in AndroidUse Lambdas in Android
Use Lambdas in Android
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascript
 
Haskell Foundations
Haskell FoundationsHaskell Foundations
Haskell Foundations
 
Java SE 8 技術手冊第 10 章 - 輸入輸出
Java SE 8 技術手冊第 10 章 - 輸入輸出Java SE 8 技術手冊第 10 章 - 輸入輸出
Java SE 8 技術手冊第 10 章 - 輸入輸出
 
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
Java SE 8 技術手冊第 14 章 - NIO 與 NIO2
 
深入淺出 Web 容器 - Tomcat 原始碼分析
深入淺出 Web 容器  - Tomcat 原始碼分析深入淺出 Web 容器  - Tomcat 原始碼分析
深入淺出 Web 容器 - Tomcat 原始碼分析
 
Java SE 8 技術手冊第 15 章 - 通用API
Java SE 8 技術手冊第 15 章 - 通用APIJava SE 8 技術手冊第 15 章 - 通用API
Java SE 8 技術手冊第 15 章 - 通用API
 
Introduction to C++ over CLI
Introduction to C++ over CLIIntroduction to C++ over CLI
Introduction to C++ over CLI
 
3, operators
3, operators3, operators
3, operators
 
Clojure简介与应用
Clojure简介与应用Clojure简介与应用
Clojure简介与应用
 
5, initialization & cleanup
5, initialization & cleanup5, initialization & cleanup
5, initialization & cleanup
 
ES5 introduction
ES5 introductionES5 introduction
ES5 introduction
 
OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)
 

Destaque

Java Web 程式之效能技巧與安全防護
Java Web 程式之效能技巧與安全防護Java Web 程式之效能技巧與安全防護
Java Web 程式之效能技巧與安全防護Justin Lin
 
JDK8 Functional API
JDK8 Functional APIJDK8 Functional API
JDK8 Functional APIJustin Lin
 
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTL
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTLServlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTL
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTLJustin Lin
 
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSP
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSPServlet & JSP 教學手冊第二版 - 第 6 章:使用 JSP
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSPJustin Lin
 
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMail
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMailServlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMail
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMailJustin Lin
 
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫Justin Lin
 
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架Justin Lin
 
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 Servlet
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 ServletServlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 Servlet
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 ServletJustin Lin
 
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章  - 物件封裝Java SE 7 技術手冊投影片第 05 章  - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝Justin Lin
 
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應Justin Lin
 
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法Justin Lin
 
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型Justin Lin
 
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計Justin Lin
 
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDEJava SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDEJustin Lin
 

Destaque (20)

Java Web 程式之效能技巧與安全防護
Java Web 程式之效能技巧與安全防護Java Web 程式之效能技巧與安全防護
Java Web 程式之效能技巧與安全防護
 
JDK8 Functional API
JDK8 Functional APIJDK8 Functional API
JDK8 Functional API
 
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTL
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTLServlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTL
Servlet & JSP 教學手冊第二版 - 第 7 章:使用 JSTL
 
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
 
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSP
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSPServlet & JSP 教學手冊第二版 - 第 6 章:使用 JSP
Servlet & JSP 教學手冊第二版 - 第 6 章:使用 JSP
 
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMail
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMailServlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMail
Servlet & JSP 教學手冊第二版 - 第 11 章:簡介 JavaMail
 
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
Servlet & JSP 教學手冊第二版 - 第 9 章:整合資料庫
 
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
 
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤
Servlet & JSP 教學手冊第二版 - 第 8 章:自訂標籤
 
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理
Servlet & JSP 教學手冊第二版 - 第 10 章:Web 容器安全管理
 
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
 
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件
 
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理
Servlet & JSP 教學手冊第二版 - 第 4 章:會話管理
 
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 Servlet
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 ServletServlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 Servlet
Servlet & JSP 教學手冊第二版 - 第 2 章:撰寫與設定 Servlet
 
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章  - 物件封裝Java SE 7 技術手冊投影片第 05 章  - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
 
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應
Servlet & JSP 教學手冊第二版 - 第 3 章:請求與回應
 
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
 
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
 
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
 
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDEJava SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
 

Semelhante a Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫

Spark调研串讲
Spark调研串讲Spark调研串讲
Spark调研串讲jie cao
 
Js is js(程劭非) (1)
Js is js(程劭非) (1)Js is js(程劭非) (1)
Js is js(程劭非) (1)looneyren
 
Metro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' ViewMetro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' ViewEric ShangKuan
 
ncuma_函數微分計算.pptx
ncuma_函數微分計算.pptxncuma_函數微分計算.pptx
ncuma_函數微分計算.pptxNCU MCL
 
函數微分_範例.pptx
函數微分_範例.pptx函數微分_範例.pptx
函數微分_範例.pptxmclmath
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档yiditushe
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1Sheng-Han Su
 
JavaScript 闭包分享(一):传递参数
JavaScript 闭包分享(一):传递参数JavaScript 闭包分享(一):传递参数
JavaScript 闭包分享(一):传递参数Janlay Wu
 
Lua 语言介绍
Lua 语言介绍Lua 语言介绍
Lua 语言介绍gowell
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍dennis zhuang
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验QLeelulu
 
分布式计算与Hadoop - 刘鹏
分布式计算与Hadoop - 刘鹏分布式计算与Hadoop - 刘鹏
分布式计算与Hadoop - 刘鹏Shaoning Pan
 
DISQL 2.0: Language for Big Data Analysis Widely Adopted in Baidu
DISQL 2.0: Language for Big Data Analysis Widely Adopted in BaiduDISQL 2.0: Language for Big Data Analysis Widely Adopted in Baidu
DISQL 2.0: Language for Big Data Analysis Widely Adopted in BaiduXiaoming Chen
 

Semelhante a Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫 (20)

Spark调研串讲
Spark调研串讲Spark调研串讲
Spark调研串讲
 
Js is js(程劭非) (1)
Js is js(程劭非) (1)Js is js(程劭非) (1)
Js is js(程劭非) (1)
 
Scala
ScalaScala
Scala
 
Metro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' ViewMetro Style Apps from C++ Developers' View
Metro Style Apps from C++ Developers' View
 
ncuma_函數微分計算.pptx
ncuma_函數微分計算.pptxncuma_函數微分計算.pptx
ncuma_函數微分計算.pptx
 
函數微分_範例.pptx
函數微分_範例.pptx函數微分_範例.pptx
函數微分_範例.pptx
 
Free Marker中文文档
Free Marker中文文档Free Marker中文文档
Free Marker中文文档
 
JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1JavaScript 快速複習 2017Q1
JavaScript 快速複習 2017Q1
 
Scala+RDD
Scala+RDDScala+RDD
Scala+RDD
 
JavaScript 闭包分享(一):传递参数
JavaScript 闭包分享(一):传递参数JavaScript 闭包分享(一):传递参数
JavaScript 闭包分享(一):传递参数
 
Ppt 136-140
Ppt 136-140Ppt 136-140
Ppt 136-140
 
Lua 语言介绍
Lua 语言介绍Lua 语言介绍
Lua 语言介绍
 
Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍Ihome inaction 篇外篇之fp介绍
Ihome inaction 篇外篇之fp介绍
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验
 
分布式计算与Hadoop - 刘鹏
分布式计算与Hadoop - 刘鹏分布式计算与Hadoop - 刘鹏
分布式计算与Hadoop - 刘鹏
 
DISQL 2.0: Language for Big Data Analysis Widely Adopted in Baidu
DISQL 2.0: Language for Big Data Analysis Widely Adopted in BaiduDISQL 2.0: Language for Big Data Analysis Widely Adopted in Baidu
DISQL 2.0: Language for Big Data Analysis Widely Adopted in Baidu
 
Ppt 127-135
Ppt 127-135Ppt 127-135
Ppt 127-135
 
Ch5
Ch5Ch5
Ch5
 
Ch5 教學
Ch5 教學Ch5 教學
Ch5 教學
 
Ch5
Ch5Ch5
Ch5
 

Mais de Justin Lin

Ch14 簡介 Spring Boot
Ch14 簡介 Spring BootCh14 簡介 Spring Boot
Ch14 簡介 Spring BootJustin Lin
 
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityCh13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityJustin Lin
 
Ch12 Spring 起步走
Ch12 Spring 起步走Ch12 Spring 起步走
Ch12 Spring 起步走Justin Lin
 
Ch11 簡介 JavaMail
Ch11 簡介 JavaMailCh11 簡介 JavaMail
Ch11 簡介 JavaMailJustin Lin
 
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Justin Lin
 
Ch09 整合資料庫
Ch09 整合資料庫Ch09 整合資料庫
Ch09 整合資料庫Justin Lin
 
Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤Justin Lin
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTLJustin Lin
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSPJustin Lin
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Justin Lin
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理Justin Lin
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應Justin Lin
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletJustin Lin
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式Justin Lin
 
14. 進階主題
14. 進階主題14. 進階主題
14. 進階主題Justin Lin
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步Justin Lin
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能Justin Lin
 
11. 常用內建模組
11. 常用內建模組11. 常用內建模組
11. 常用內建模組Justin Lin
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換Justin Lin
 
9. 資料結構
9. 資料結構9. 資料結構
9. 資料結構Justin Lin
 

Mais de Justin Lin (20)

Ch14 簡介 Spring Boot
Ch14 簡介 Spring BootCh14 簡介 Spring Boot
Ch14 簡介 Spring Boot
 
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/SecurityCh13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/Security
 
Ch12 Spring 起步走
Ch12 Spring 起步走Ch12 Spring 起步走
Ch12 Spring 起步走
 
Ch11 簡介 JavaMail
Ch11 簡介 JavaMailCh11 簡介 JavaMail
Ch11 簡介 JavaMail
 
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理Ch10 Web 容器安全管理
Ch10 Web 容器安全管理
 
Ch09 整合資料庫
Ch09 整合資料庫Ch09 整合資料庫
Ch09 整合資料庫
 
Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTL
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSP
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
 
14. 進階主題
14. 進階主題14. 進階主題
14. 進階主題
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能
 
11. 常用內建模組
11. 常用內建模組11. 常用內建模組
11. 常用內建模組
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換
 
9. 資料結構
9. 資料結構9. 資料結構
9. 資料結構
 

Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫

  • 1. Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
  • 2. 林信良 http://openhome.cc caterpillar@openhome.cc
  • 3. 議程 • 一級函式與 λ 演算 • JDK8 的 Lambda 語法 • 介面預設方法(Default method) • 擴充的 Collection 框架 • 函數式風格的可能性
  • 4. 一級函式與 λ 演算 第十一個希臘字母 物理上的波長符號 放射學的衰變常數 線性代數的特徵值 λ 演算 ….
  • 6. 一級函式 • 有些語言中函式是一等公民(First-class citizen) – 高階函式(High order function) function doSome(param) { // 作些事 } var doSome = function(param) { // 作些事 };
  • 7. 一級函式 • 有些語言中函式是一等公民(First-class citizen) – 高階函式(High order function) function doSome(param) { // 作些事 } var doSome = function(param) { // 作些事 }; doOther(function(param) { function(param) // 作些事 // 作些事 }); };
  • 8. 一級函式 • 有些語言中函式是一等公民(First-class citizen) – 高階函式(High order function) function doSome(param) { // 作些事 } var doSome = function(param) { // 作些事 }; function doAction(opt) { return function(param) { // 作些事 作些事 // }; }; };
  • 9. What is http://en.wikipedia.org/wiki/Lambda In programming languages such as Lisp and Python, lambda is an operator used to denote anonymous functions or closures /lambda/
  • 10. λ 演算(Lambda calculus) • 每個表達式(Expression)代表具單一參數函數 • 參數本身亦可接受具有單一參數的函式 • f(x) = x * 2 可匿名地表示為 … λ x. x * 2 x -> x * 2
  • 11. λ 演算(Lambda calculus) • 如果要套用 x 為 2 (x -> x * 2)(2) = 2 * 2 = 4 • g(y) = y -1 代入 f(x) 匿名地表達為… (y -> y - 1)(x -> x * 2) = x -> x * 2 - 1
  • 12. λ 演算(Lambda calculus) • 多參數的函數可使用單參數函數套用而成 (x, y) -> x * x + y * y = x -> (y -> x * x + y * y) •若x為2而y為3 (x -> (y -> x * x + y * y))(2)(3) = (y -> 2 * 2 + y * y)(3) = 4 + 3 * 3 = 4 + 9 = 13
  • 13. λ 演算(Lambda calculus) • 可用來表現任何可計算函數 • 可使用函數實現控制結構(如 if、forEach等) • 一個小型通用語言 butThat = cond->fv->tv-> (cond or fv) and (cond and tv) butThat(true)(10)(20) = (true or 10) and (true and 20) = true and 20 = 20
  • 14. 一級函式與 λ 演算 • 不同語言提供不同程度的 Lambda 表達式支援 (x -> x * 2)(2) function(x) { return x * 2; }(2);
  • 15. 一級函式與 λ 演算 • JDK8 前存在 Lambda 語法類似品 – 匿名內部類別(Anonymous inner class) • 定義單一抽象方法(Single abstract method)介 面模擬一級函式 interface Func<P, R> { R apply(P p); }
  • 16. 一級函式與 λ 演算 • 使用匿名內部類別來表示 x -> x * 2 new Func<Integer, Integer>() { public Integer apply(Integer x) { return x * 2; } };
  • 17. 一級函式與 λ 演算 • 設計 compose(f, g) 達成 g(f(x)) 的函數組合 static <A, B, C> Func<A, C> compose( final Func<A, B> f, final Func<B, C> g) { return new Func<A, C>() { public C apply(A x) { return g.apply(f.apply(x)); } }; }
  • 18. 一級函式與 λ 演算 • f(x) = x + 2 而 g(y) = y * 3 • h(x) = g(f(x)) compose( new Func<Integer, Integer>() { public Integer apply(Integer x) { return x + 2; } }, new Func<Integer, Integer>() { public Integer apply(Integer y) { return y * 3; } } );
  • 19. JDK8 的 Lambda 語法 λ
  • 20. JDK8 的 Lambda 語法 • 使用 JDK8 的 Lambda 語法來表示 x -> x * 2 (Integer x) -> x + 2 • 設計 compose(f, g) 達成 g(f(x)) 的函數組合 static <A, B, C> Func<A, C> compose(Func<A, B> f, Func<B, C> g) { // 忽略.apply 就是 x -> g(f(x)) return x -> g.apply(f.apply(x)); } • f(x) = x + 2 、 g(y) = y * 3、h(x) = g(f(x)) compose((Integer x) -> x + 2, (Integer y) -> y * 3)
  • 21. JDK8 的 Lambda 表示式 • (type parameter) -> function_body – 單一運算式 (int x, int y) -> x + y () -> 42 – 陳述區塊 (String s) -> { System.out.println(s); }
  • 22. 函式介面(Functional interface) • 單一抽象方法的介面 public interface Runnable { void run(); } public interface Comparator<T> { int compare(T o1, T o2); } public interface Callable<V> { V call() throws Exception }
  • 23. 目標定型(Target typing) • 目標型態與環境(Context)有關 – 目標型態可用於類型推斷(Type inference) Runnable r = () -> { out.println("later"); }; Comparator<String> c = (s1, s2) -> s1.compareTo(s2); Collections.sort(lists, (s1, s2) -> -s1.compareTo(s2)); • 獨立於型態的Lambda 表示式 Callable<String> c = () -> "done"; PrivilegedAction<String> a = () -> "done";
  • 24. 不只是語法蜜糖 • 語彙範圍(Lexical scoping) – Lambda 語法本體中的名稱與包裹環境相同 public class Hello { Runnable r1 = () -> { out.println(this); } Runnable r2 = () -> { out.println(toString()); } public String toString() { return "Hello, world!"; } public static void main(String... args) { new Hello().r1.run(); new Hello().r2.run(); } }
  • 25. 不只是語法蜜糖 • 變數捕捉(Variable capture) – 與 final 等效的區域變數不需要 final Callable<String> helloCallable(String name) { String hello = "Hello"; return () -> (hello + ", " + name); } • 編譯錯誤... int sum = 0; list.forEach(e -> { sum += e.size(); }); • 建議... int sum = list.map(e -> e.size()) .reduce(0, (a, b) -> a + b);
  • 26. 方法參考(Method reference) • 類別靜態方法 public class Person { ... public static int compareByAge(Person a, Person b) { ... } public static int compareByName(Person a, Person b) { ... } } Person[] people = ... // Arrays.sort(people, (a, b) -> a.getAge() – b.getAge()); Arrays.sort(people, Person::compareByAge); interface Block<T> { void run(T arg); } Block<Integer> b1 = System::exit; // void exit(int status) Block<String[]> b2 = Arrays::sort; // void sort(Object[] a) Block<String> b3 = MyProgram::main; // void main(String... args) Runnable r = MyProgram::main; // void main(String... args)
  • 27. 方法參考(Method reference) • 特定物件實例方法 public class ComparisonProvider { public int compareByName(Person p1, Person p2) { ... } public int compareByAge(Person p1, Person p2) { ... } } ... ComparisonProvider comparisonProvider = ...; Arrays.sort(people, comparisonProvider::compareByName); • 實例方法中可帶物件狀態 – 相當於讓 Lambda 語法帶有狀態(Closure 的替代?)
  • 28. 方法參考(Method reference) • 任意類別的實例方法 List<String> names = Arrays.asList("Justin", ...); Collections.sort(names, (s1, s2) -> s1.compareToIgnoreCase(s2)); Collections.sort(names, String::compareToIgnoreCase);
  • 29. 方法參考(Method reference) • 讓 Lambda 語法的目標類型可以變換 Callable<String> c = () -> "done"; PrivilegedAction<String> a = c::call;
  • 32. 介面預設方法(Default method) • JDK8 前實作介面以實現多個規格的繼承來源 – 捨棄繼承多個實作來源的可能性,規避了多重繼承下實 作衝突等問題 public class Ball implements Comparable<Ball> { public boolean notEquals(Ball that) { return this.radius - that.radius; } // 底下都是根據notEquals()實作 public boolean lessThan(Ball that) { return this.notEquals(that) < 0; } public boolean lessOrEquals(Ball that) { return this.lessThan(that) || this.notEquals(that) == 0; } public boolean greaterThan(Ball that) { return !this.lessOrEquals(that); } ...
  • 33. 介面預設方法(Default method) • JDK8 介面可以是根據抽象的共用實作 public interface Comparable<T> { boolean notEquals(T that); boolean lessThan(T that) default { return this.notEquals(that) < 0; } boolean lessOrEquals(T that) default { return this.lessThan(that) || this.notEquals(that) == 0; } boolean greaterThan(T that) default { return !this.lessOrEquals(that); } ...
  • 34. 介面預設方法(Default method) • JDK8 可以實作具有預設方法的介面 public class Ball implements Comparable<Ball> { public boolean notEquals(Ball that) { return this.radius - that.radius; } ... • 實作可能發生衝突.. interface Robot implements Artist, Gun { void draw() default { Artist.super.draw(); } }
  • 35. 介面預設方法(Default method) • 擴充既有程式庫以搭配 Lambda 語法 – 僅在介面中新增方法定義? – 使用靜態方法?像是 Collections.filter(…)? – 獨立的新 API?像是 Collection2 框架? interface Iterator<E> { boolean hasNext(); E next(); void remove(); void skip(int i) default { for (; i > 0 && hasNext(); i--) next(); } }
  • 36. 擴充的 Collection 框架 • 高階函式 – 可讀性 – 簡潔性 – 導入新的抽象層 • 以迭代為例… for(Ball b : balls) { b.setColor(RED); } balls.forEach(b -> { b.setColor(RED); });
  • 37. 擴充的 Collection 框架 • 匿名類別作不到嗎? – 想分離關切點,但又帶入新的關切點 balls.forEach(new Block<Ball> { public void apply(Ball ball) { ball.setColor(RED); } }); • 傳入 Lambda 表示式,而非傳入不想要的雜訊
  • 38. 擴充的 Collection 框架 • 為什麼是 Collection 框架? • 許多問題都是資料處理問題… – 關聯式資料通常就是待處理資料群集… • filter、map、fold 等是處理資料時的高階抽象 – 過濾一組資料 – 將一組資料對應至另一組資料 – 逐一取得資料計算單一結果 – …
  • 39. 擴充的 Collection 框架 • 管線化(Piped)操作 int sum = names.filter(s -> s.length() < 3) .map(s -> s.length()) .reduce(0, (sum, len) -> sum + len); int sum = names.filter(s -> s.length() < 3) .map(s -> s.length()) .sum();
  • 40. 擴充的 Collection 框架 • 管線化(Piped)操作 blocks.filter(b -> b.getColor() == BLUE) .forEach(b -> { b.setColor(RED); }); List<Block> blue = blocks.filter(b -> b.getColor() == BLUE) .into(new ArrayList<>()); Set<Box> blueBlock = blocks.filter(b -> b.getColor() == BLUE) .map(b -> b.getContainingBox()) .into(new HashSet<>());
  • 41. 擴充的 Collection 框架 • 延遲(Laziness) int sum = blocks.filter(b -> b.getColor() == BLUE) .map(b -> b.getWeight()) .sum(); • 捷徑(short-circuiting) Block firstBlue = blocks.filter(b -> b.getColor() == BLUE) .getFirst();
  • 42. 擴充的 Collection 框架 • 共用的函式介面(java.util.functions) – Predicate – boolean test(T t) – Block – void apply(T t); – Mapper – U map(T t) – ...
  • 43. 擴充的 Collection 框架 • 已實作 filter、map 與 fold 的細節 – 循序? – 遞迴? – 共用資料結構? – 平行化? • 可以用更高階的抽象來處理資料 int sum = blocks.parallel() .filter(b -> b.getColor() == BLUE) .map(b -> b.getWeight()) .sum();
  • 44. 全部放在一起 for (Method m : enclosingInfo.getEnclosingClass().getDeclaredMethods()) { if (m.getName().equals(enclosingInfo.getName()) ) { Class<?>[] candidateParamClasses = m.getParameterTypes(); if (candidateParamClasses.length == parameterClasses.length) { boolean matches = true; for(int i = 0; i < candidateParamClasses.length; i++) { if (!candidateParamClasses[i].equals(parameterClasses[i])) { matches = false; break; } } if (matches) { // finally, check return type if (m.getReturnType().equals(returnType) ) return m; } } } } throw new InternalError("Enclosing method not found");
  • 45. 全部放在一起 Method matching = Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods()) .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName()) .filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses)) .filter(m -> Objects.equals(m.getReturnType(), returnType)) .getFirst(); if (matching == null) throw new InternalError("Enclosing method not found"); return matching;
  • 46. 全部放在一起 List<Album> favs = new ArrayList<>(); for (Album a : albums) { boolean hasFavorite = false; for (Track t : a.tracks) { if (t.rating >= 4) { hasFavorite = true; break; } } if (hasFavorite) favs.add(a); } Collections.sort(favs, new Comparator<Album>() { public int compare(Album a1, Album a2) { return a1.name.compareTo(a2.name); }});
  • 47. 全部放在一起 List<Album> sortedFavs = albums.filter(a -> a.tracks.anyMatch(t -> (t.rating >= 4))) .sortedBy(a -> a.name) .into(new ArrayList<>());
  • 49. 函數式風格的可能性 • Lambda 語法在原語言中提供小型通用語言 • 在某些問題領域… – 提供以 λ 演算解題的可能性 • Java 在函數式程式設計(Functional Parogramming)的可能性?
  • 50. 函數式風格的可能性 • 費式數的定義 { F0 = 0, F1 = 1, Fn = Fn-1 + Fn-2 } • 指令式程式設計(Imperative programming)? int fib(int n) { int a = 1; int b = 1; for(int i = 2; i < n; i++) { int tmp = b; b = a + b; a = tmp; } return b; }
  • 51. 函數式風格的可能性 • 函數式程式設計? int fib(int n) { if(n == 0 || n == 1) return n; else return fib(n - 1) + fib(n - 2); } • 使用 Haskell fib 0 = 0 fib 1 = 1 fib n = fib (n-1) + fib (n-2)
  • 52. 函數式風格的可能性 • 函數式語言的特徵 fib 0 = 0 fib 1 = 1 – 一級函式 fib n = fib (n-1) + fib (n-2) – Immutable sum [] = 0 – Lazy evaluation sum (x:xs) = x + sum xs – Pattern match {2 * x | x ∈ {1, 2..100}} – List comprehension [2 * x | x <- [1, 2..100]] – Curried function f x y = x + y g y = f 1 y
  • 53. 函數式風格的可能性 • JDK8 有多少函數式風格的特性? – 直接支援 Lambda 語法 – 使用 final 變數強制 Immutable – 以 API 封裝複雜細節達到… – 延遲求值 – 模式匹配 – List comprehension – Partially applied 與 Curried function
  • 54. 函數式風格的可能性 • 以 API 封裝複雜細節,留下函數式外觀給使用者 – Functional Java(functionaljava.org) – 目的就是為了讓 Java 實現函數式風格 – 主要針對 JDK5 以上 – 使用匿名內部類別繼承抽象類別 final Array<String> a = array("Hello", "There", "what"); final boolean b = a.exists(new F<String, Boolean>() { public Boolean f(final String s) { return fromString(s).forall(isLowerCase); } }); boolean b = a.exists(s -> fromString(s).forall(isLowerCase));
  • 55. 函數式風格的可能性 • 以 API 封裝複雜細節,留下函數式外觀給使用者 – Guava(code.google.com/p/guava-libraries) – 主要目的並非為了讓 Java 實現函數式風格 – 主要針對 JDK5 以上 – 使用匿名內部類別實作介面
  • 56. 函數式風格的可能性 • Guava 目前不鼓勵函數式風格 Multiset<Integer> lengths = HashMultiset.create( FluentIterable.from(strings) .filter(new Predicate<String>() { public boolean apply(String string) { return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string); } }) .transform(new Function<String, Integer>() { public Integer apply(String string) { return string.length(); } })); Multiset<Integer> lengths = HashMultiset.create( FluentIterable.from(strings) .filter(s -> CharMatcher.JAVA_UPPER_CASE.matchesAllOf(s)) .transform(s -> s.length()) ));
  • 57. 總結 • λ 語法為 Java 提供了小型通用語言,在某些問題 領域,提供 λ 演算解題的可能性 • 除 JDK 程式庫將搭配 λ 語法演化,開放原始碼如 Functional Java、Guava 等也將呈現不同風格 • 新的抽象層將平行化、函數式等實作予以封裝, 簡潔的表述能力,使開發者進一步思索 map、 filter、fold 等問題的基本形式
  • 58. 參考資料 • State of the Lambda v4 – http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html • State of the Lambda: Libraries Edition – http://cr.openjdk.java.net/~briangoetz/lambda/collections- overview.html • Project Lambda – http://openjdk.java.net/projects/lambda/ • Lambda calculus – http://en.wikipedia.org/wiki/Lambda_calculus • Functional Programming for Java Developers – http://shop.oreilly.com/product/0636920021667.do • APIO讲稿——函数式编程 – http://www.byvoid.com/blog/apio-fp/