I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0
          <2014年11月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          常用鏈接

          留言簿(5)

          隨筆分類(lèi)(161)

          隨筆檔案(114)

          文章分類(lèi)(2)

          文章檔案(2)

          Alibaba

          Comprehensive

          Expert

          Game

          Java

          搜索

          •  

          積分與排名

          • 積分 - 599944
          • 排名 - 78

          最新評(píng)論

          閱讀排行榜

             本篇用代碼的方式并結(jié)合自己對(duì)Lamba的理解講了Java8的Lambda表達(dá)式及函數(shù)式接口相關(guān)。
             參考:http://winterbe.com/posts/2014/03/16/java-8-tutorial/

             1.接口中擴(kuò)展方法(default關(guān)鍵字)

          package com.mavsplus.java8.turtorial.one;

          /**
           * 公式接口
           * <p>
           * Java 8 允許我們使用default關(guān)鍵字,為接口聲明添加非抽象的方法實(shí)現(xiàn)。這個(gè)特性又被稱(chēng)為擴(kuò)展方法
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public interface Formula {
              public double calculate(int a);

              /**
               * 默認(rèn)的非抽象方法(default關(guān)鍵字)
               * 
               * @param a
               * @return
               
          */
              default double sqrt(int a) {
                  return Math.sqrt(a);
              }

              /**
               * 增加了public 關(guān)鍵字
               * 
               * @param a
               * @return
               
          */
              public default double sin(int a) {
                  return Math.sin(a);
              }

              /**
               * 測(cè)試該特性
               * <p>
               * Run As Java Application的時(shí)候會(huì)出現(xiàn)兩個(gè)選擇,因?yàn)槌薋ormula接口類(lèi),還有一個(gè)內(nèi)部類(lèi)Formula$1
               * 
               * @param args
               
          */
              public static void main(String args) {
                  // 匿名內(nèi)部類(lèi)的方式
                  Formula formula = new Formula() {

                      @Override
                      public double calculate(int a) {
                          // 調(diào)用了默認(rèn)的非抽象方法
                          return sqrt(a * 100);
                      }
                  };

                  System.out.println(formula.calculate(144));
                  // 直接調(diào)用默認(rèn)的非抽象方法
                  System.out.println(formula.sqrt(225));
              }
          }

              2.Lamba表達(dá)式小試牛刀

          package com.mavsplus.java8.turtorial.lambda;

          import java.util.Arrays;
          import java.util.Collections;
          import java.util.Comparator;
          import java.util.List;

          /**
           * 字符串列表排序,使用java8之前實(shí)現(xiàn)及java8 lambda實(shí)現(xiàn)
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public class ListOfStringSort {

              private List<String> names = Arrays.asList("landon", "kobe", "dirk", "tmac");

              /**
               * 舊版本實(shí)現(xiàn),使用匿名內(nèi)部類(lèi)
               
          */
              public void oldVersionSort() {
                  Collections.sort(names, new Comparator<String>() {

                      @Override
                      public int compare(String o1, String o2) {
                          return o2.compareTo(o1);
                      }
                  });
              }

              /**
               * 使用Lambda表達(dá)式實(shí)現(xiàn)1
               * <p>
               * 從語(yǔ)法上看,(String o1, String o2)為Comparator接口中compare方法的兩個(gè)參數(shù),沒(méi)有方法名; -> 為方法的實(shí)現(xiàn)
               * 此表達(dá)式返回一個(gè)Comparator對(duì)象
               * (編譯器知道Collection.sort第二個(gè)參數(shù)是一個(gè)Comparator接口實(shí)現(xiàn)的對(duì)象,而該接口只有一個(gè)方法compare
               * ->個(gè)人認(rèn)為編譯器解釋該lambda表達(dá)式的時(shí)候也會(huì)轉(zhuǎn)為匿名內(nèi)部類(lèi)的方式實(shí)現(xiàn))
               
          */
              public void lambdaSort1() {
                  Collections.sort(names, (String o1, String o2) -> {
                      return o2.compareTo(o1);
                  });
              }

              /**
               * 使用Lambda表達(dá)式實(shí)現(xiàn)2
               * <p>
               * 這個(gè)實(shí)現(xiàn)更加簡(jiǎn)單,較第一個(gè)版本沒(méi)有了大括號(hào)和return(個(gè)人認(rèn)為因?yàn)榫幾g器能推斷出返回類(lèi)型)
               
          */
              public void lambdaSort2() {
                  Collections.sort(names, (String o1, String o2) -> o2.compareTo(o1));
              }

              /**
               * 使用Lambda表達(dá)式實(shí)現(xiàn)3
               * <p>
               * 這是是最簡(jiǎn)單的實(shí)現(xiàn),類(lèi)型都可以省略不寫(xiě).因?yàn)镴ava編譯器能夠自動(dòng)識(shí)別參數(shù)的類(lèi)型(注,用ide編輯代碼的時(shí)候,敲o2.的時(shí)候,
               * 自動(dòng)會(huì)出現(xiàn)String的方法_智能提示)
               
          */
              public void lambdaSort3() {
                  Collections.sort(names, (o1, o2) -> o2.compareTo(o1));
              }
          }

              3.函數(shù)式接口(@FunctionalInterface)

          package com.mavsplus.java8.turtorial.lambda;

          /**
           * Lambda函數(shù)式接口
           * 
           * <pre>
           * Lambda表達(dá)式如何匹配Java的類(lèi)型系統(tǒng)?
           * 每一個(gè)lambda都能夠通過(guò)一個(gè)特定的接口,與一個(gè)給定的類(lèi)型進(jìn)行匹配。
           * 一個(gè)所謂的函數(shù)式接口必須要有且僅有一個(gè)抽象方法聲明,每個(gè)與之對(duì)應(yīng)的lambda表達(dá)式必須要與抽象方法的聲明相匹配。
           * 由于默認(rèn)方法不是抽象的,因此你可以在你的函數(shù)式接口里任意添加默認(rèn)方法。
           * 任意只包含一個(gè)抽象方法的接口,我們都可以用來(lái)做成lambda表達(dá)式。
           * 為了讓你定義的接口滿(mǎn)足要求,你應(yīng)當(dāng)在接口前加上@FunctionalInterface標(biāo)注。
           * 編譯器會(huì)注意到這個(gè)標(biāo)注,如果你的接口中定義了第二個(gè)抽象方法的話,編譯器會(huì)拋出異常。
           * </pre>
           * 
           * <pre>
           * @FunctionalInterface public interface Runnable {}
           * @FunctionalInterface public interface Comparator<T> {}
           * 
           * 從JDK 1.8的源碼可以看到,一些常用接口都加上了@FunctionalInterface關(guān)鍵字,即都是函數(shù)式接口->都可以用Lambda表達(dá)式進(jìn)行匹配
           * </pre>
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public class LambdaFunctionalInterface {

              /**
               * 自定義的一個(gè)函數(shù)式接口.->轉(zhuǎn)換器,將F(From)類(lèi)型轉(zhuǎn)為T(mén)(Target)類(lèi)型
               *
               * @param <F>
               * @param <T>
               
          */
              @FunctionalInterface
              public interface Converter<F, T> {
                  T convert(F from);
              }

              public static void main(String args) {
                  // 使用lamba表達(dá)式1,(from)為convert參數(shù)列表 -> 方法實(shí)現(xiàn)
                  Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
                  System.out.println(converter.convert("123"));

                  // 使用lambda表達(dá)式2,這里加上了大括號(hào)和返回值,這樣更直觀一些,->左邊為參數(shù)列表,右邊為方法實(shí)現(xiàn)
                  Converter<String, Integer> converter2 = (String from) -> {
                      return Integer.valueOf(from);
                  };
                  System.out.println(converter2.convert("456"));

                  // 使用lambda表達(dá)式3,這里和第一個(gè)的區(qū)別是加上了參數(shù)類(lèi)型
                  Converter<String, Integer> converter3 = (String from) -> Integer.valueOf(from);
                  System.out.println(converter3.convert("789"));

                  // 注:本例的Converter接口也可以不加@FunctionalInterface這個(gè)注解,因?yàn)閮?nèi)部本身只有一個(gè)抽象方法
              }
          }

              4.::關(guān)鍵字獲取方法或者構(gòu)造函數(shù)的的引用(::)

          package com.mavsplus.java8.turtorial.lambda;

          import com.mavsplus.java8.turtorial.lambda.LambdaFunctionalInterface.Converter;

          /**
           * 方法和構(gòu)造函數(shù)引用
           * 
           * <pre>
           * Java 8 允許你通過(guò)::關(guān)鍵字獲取方法或者構(gòu)造函數(shù)的的引用
           * </pre>
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public class MethodConstructorRef {
              /**
               * 引用靜態(tài)方法
               
          */
              public void refStaticMethod() {
                  // 使用靜態(tài)方法引用::,賦值(個(gè)人認(rèn)為編譯器會(huì)處理一切-,>因?yàn)槭呛瘮?shù)式接口)
                  
          // 該種方式是相當(dāng)于通過(guò)右側(cè)方法引用實(shí)現(xiàn)了函數(shù)式接口的實(shí)現(xiàn).
                  Converter<String, Integer> converter = Integer::valueOf;
                  System.out.println(converter.convert("365"));
              }

              /**
               * 定義一個(gè)內(nèi)部類(lèi)
               
          */
              public class Something {
                  /**
                   * 定義了一個(gè)參數(shù)是字符串,返回值也是字符串的方法
                   * 
                   * @param s
                   * @return
                   
          */
                  public String startsWith(String s) {
                      return String.valueOf(s.charAt(0));
                  }
              }

              /**
               * 對(duì)一個(gè)對(duì)象的方法進(jìn)行引用
               
          */
              public void refObjectMethod() {
                  Something something = new Something();

                  // 將something對(duì)象的startsWith方法引用賦值::
                  
          // 該種方式是相當(dāng)于通過(guò)右側(cè)方法引用實(shí)現(xiàn)了函數(shù)式接口的實(shí)現(xiàn).
                  Converter<String, String> converter = something::startsWith;
                  System.out.println(converter.convert("Lambda"));
              }

              /**
               * 自定義的一個(gè)JavaBean
               
          */
              public class Person {
                  private String firstName;
                  private String lastName;

                  public Person() {

                  }

                  public Person(String fName, String lName) {
                      firstName = fName;
                      lastName = lName;
                  }

                  public String getFirstName() {
                      return firstName;
                  }

                  public String getLastName() {
                      return lastName;
                  }
              }

              /**
               * 自定義了一個(gè)接口,接口內(nèi)部有兩個(gè)字符串參數(shù)的方法
               *
               * @param <P>
               
          */
              public interface PersonFactory<P extends Person> {
                  public P create(String firstName, String lastName);
              }

              /**
               * 通過(guò)::對(duì)構(gòu)造方法進(jìn)行引用
               * Person::new來(lái)創(chuàng)建一個(gè)Person類(lèi)構(gòu)造函數(shù)的引用。Java編譯器會(huì)自動(dòng)地選擇合適的構(gòu)造函數(shù)來(lái)匹配PersonFactory
               * .create函數(shù)的簽名,并選擇正確的構(gòu)造函數(shù)形式
               
          */
              public void refConstructor() {
                  PersonFactory<Person> factory = Person::new;

                  Person p = factory.create("kobe", "bryant");

                  System.out.println(p.getFirstName() + "_" + p.getLastName());
              }

              /**
               * 這里是想測(cè)試一下,如果接口內(nèi)兩個(gè)抽象方法,能否使用方法引用匹配,因?yàn)镻erson確實(shí)是有兩個(gè)構(gòu)造方法
               * 結(jié)論:不行,方法引用只能是functional
               * interface.(個(gè)人認(rèn)為這樣也是非常合理的->因?yàn)橛覀?cè)的方法引用只能是確定的一個(gè)方法,不可能匹配對(duì)個(gè)抽象方法
               * --雖然構(gòu)造方法可以有多個(gè),但畢竟是
               * ::的特例,特例不能決定全部,而從實(shí)現(xiàn)的角度來(lái)看,會(huì)大大加大編譯器的處理難度,而且只能是針對(duì)引用構(gòu)造方法對(duì)多個(gè)抽象方法進(jìn)行特殊處理
               * .——————當(dāng)然同一個(gè)方法也有多種不同的重載形式
               * ,不過(guò)會(huì)大大加大編譯器的處理難度-------另一個(gè)原因我認(rèn)為可能是為了要和lambda表達(dá)式處理一致
               * .lambda表達(dá)式本來(lái)就是要處理簡(jiǎn)單,它不可能在一個(gè)表達(dá)式中實(shí)現(xiàn)多個(gè)抽象方法)
               
          */
              public interface PersonFactory2<P extends Person> {
                  public P create(String firstName, String lastName);

                  public P create();
              }

              // 這里出現(xiàn)編譯錯(cuò)誤:The target type of this expression must be a functional
              
          // interface
              public void refConstructor2() {
                  // PersonFactory2<Person> factory = Person::new;
              }
              
              public static void main(String[] args) {
                  MethodConstructorRef ref = new MethodConstructorRef();
                  
                  ref.refStaticMethod();
                  ref.refObjectMethod();
                  ref.refConstructor();
              }
          }


              5.Lambda表達(dá)式訪問(wèn)范圍
              
          package com.mavsplus.java8.turtorial.lambda;

          import com.mavsplus.java8.turtorial.lambda.LambdaFunctionalInterface.Converter;

          /**
           * Lambda的范圍
           * <p>
           * 對(duì)于lambdab表達(dá)式外部的變量,其訪問(wèn)權(quán)限的粒度與匿名對(duì)象的方式非常類(lèi)似。你能夠訪問(wèn)局部對(duì)應(yīng)的外部區(qū)域的局部final變量_enclosing(
           * 注_針對(duì)局部變量, 而對(duì)于外部類(lèi)變量[成員變量]則無(wú)此限制 by landon),以及成員變量和靜態(tài)變量
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public class LambdaRange {
              /**
               * Lambda訪問(wèn)Final局部變量
               
          */
              public void lambdaAccessLocalFinalVar() {
                  final int num = 1;

                  // 這里直接訪問(wèn)num
                  Converter<Integer, String> converter = (from) -> String.valueOf(from + num);

                  // 輸出3
                  System.out.println(converter.convert(2));
              }

              /**
               * Lambda訪問(wèn)非Final局部變量
               * <p>
               * 但是與匿名對(duì)象不同的是,變量num并不需要一定是final.
               
          */
              public void lambdaAccessLocalNonFinalVar() {
                  int num2 = 2;

                  // 這里直接訪問(wèn)num2
                  
          // num2在編譯的時(shí)候被隱式地當(dāng)做final變量來(lái)處理
                  Converter<Integer, String> converter = (from) -> String.valueOf(from + num2);

                  // 輸出4
                  System.out.println(converter.convert(2));
              }

              /**
               * Lambda嘗試改變非final局部變量
               * <p>
               * 在lambda表達(dá)式內(nèi)部企圖改變num3的值也是不允許的(因?yàn)殡[式做final處理)
               
          */
              public void lambdaModifyLocalNonFinalVar() {
                  int num3 = 3;

                  Converter<Integer, String> converter = (from) -> String.valueOf(from + num3);
                  converter.convert(3);

                  // 加上這句賦值,修改了非final局部變量num3,則編譯錯(cuò)誤
                  
          // 報(bào)編譯錯(cuò)誤:Local variable num3 defined in an enclosing scope must be
                  
          // final or effectively final
                  
          // num3 = 4;
              }

              private int outerNum = 4;
              private static int outerStaticNum = 5;

              /**
               * Lambda訪問(wèn)成員變量
               * <p>
               * 與局部變量不同,我們?cè)趌ambda表達(dá)式的內(nèi)部能獲取到對(duì)成員變量或靜態(tài)變量的讀寫(xiě)權(quán)。這種訪問(wèn)行為在匿名對(duì)象里是非常典型的 ---此規(guī)則同匿名對(duì)象
               
          */
              public void lambdaAccessMemberAndStaticVar() {
                  // 訪問(wèn)外部成員變量
                  Converter<Integer, String> converter1 = (from) -> {
                      outerNum = 8;
                      return String.valueOf(from);
                  };

                  converter1.convert(4);

                  // 訪問(wèn)外部靜態(tài)成員變量
                  Converter<Integer, String> converter2 = (from) -> {
                      outerStaticNum = 11;
                      return String.valueOf(from);
                  };

                  converter2.convert(5);
              }

              /**
               * lambda訪問(wèn)默認(rèn)方法
               * <p>
               * 默認(rèn)方法無(wú)法在lambda表達(dá)式內(nèi)部被訪問(wèn)
               
          */
              public void lambdaAccessDefaultInterfaceMethod() {
                  // Formula是一個(gè)接口,接口中一個(gè)抽象的calculate方法和一個(gè)默認(rèn)方法sqrt
                  
          // 這里編譯錯(cuò)誤,The method sqrt(int) is undefined for the type LambdaRange
                  
          // 從上面的編譯錯(cuò)誤可以看出,編譯器根本是不知道sqrt這個(gè)方法的存在,它在當(dāng)前類(lèi)中也沒(méi)有找到該方法的聲明
                  
          // 這樣做是非常合理的->編譯器第一步是要先確認(rèn)-> 右邊的這個(gè)方法表達(dá)式是否存在(不可能先去接口里是不是默認(rèn)方法->實(shí)現(xiàn)復(fù)雜度加大)
                  
          // 而用匿名類(lèi)對(duì)象當(dāng)然可以,因?yàn)槟涿?lèi)就是實(shí)現(xiàn)了該接口并繼承了默認(rèn)方法,按照類(lèi)繼承的規(guī)則當(dāng)然可以進(jìn)行訪問(wèn)
                  
          // Formula formula = (a) -> sqrt(a * 100);
              }

              public static void main(String[] args) {
                  LambdaRange range = new LambdaRange();

                  range.lambdaAccessLocalFinalVar();
                  range.lambdaAccessLocalNonFinalVar();

                  System.out.println("pre_OuterNum:" + range.outerNum);
                  System.out.println("pre_OuterStaticNum:" + outerStaticNum);

                  // 此方法會(huì)改變成員變量和靜態(tài)變量的值_lambda表達(dá)式對(duì)其進(jìn)行了修改
                  range.lambdaAccessMemberAndStaticVar();

                  System.out.println("post_OuterNum:" + range.outerNum);
                  System.out.println("post_OuterStaticNum:" + outerStaticNum);
              }
          }

              6.Java8內(nèi)置的函數(shù)式接口

          package com.mavsplus.java8.turtorial.lambda;

          import java.util.Comparator;
          import java.util.Objects;
          import java.util.Optional;
          import java.util.function.Consumer;
          import java.util.function.Function;
          import java.util.function.Predicate;
          import java.util.function.Supplier;

          import com.mavsplus.java8.turtorial.lambda.MethodConstructorRef.Person;

          /**
           * Java8內(nèi)置函數(shù)式接口
           * 
           * <pre>
           * JDK 1.8 API中包含了很多內(nèi)置的函數(shù)式接口。有些是在以前版本的Java中大家耳熟能詳?shù)模鏑omparator接口,或者Runnable接口。
           * 對(duì)這些現(xiàn)成的接口進(jìn)行實(shí)現(xiàn),可以通過(guò)@FunctionalInterface 標(biāo)注來(lái)啟用Lambda功能支持。 
           * 此外,Java 8 API 還提供了很多新的函數(shù)式接口,來(lái)降低程序員的工作負(fù)擔(dān)。有些新的接口已經(jīng)在Google Guava庫(kù)中很有名了。
           * 如果你對(duì)這些庫(kù)很熟的話,你甚至閉上眼睛都能夠想到,這些接口在類(lèi)庫(kù)的實(shí)現(xiàn)過(guò)程中起了多么大的作用.
           * </pre>
           * 
           * <p>
           * 可以搜索FunctionalInterface的引用,發(fā)現(xiàn)諸如Runnable,Comparator,Callbale等接口在JDK8中均加了該注解。
           * 另外可以看到在java.util中增加了一個(gè)function
           * package,即java.util.function,該package即內(nèi)置了很多函數(shù)式接口.
           * 
           * @author landon
           * @since 1.8.0_25
           
          */
          public class LambdaBuildInFunctionalInterface {

              /**
               * Predicate是一個(gè)布爾類(lèi)型的函數(shù),該函數(shù)只有一個(gè)輸入?yún)?shù)。Predicate接口包含了多種默認(rèn)方法,用于處理復(fù)雜的邏輯動(dòng)詞(and,
               * or,negate_(not)),可以查看其源碼
               * 
               * @FunctionalInterface public interface Predicate<T>{ boolean test(T t);
               
          */
              public void usePredicate() {
                  // 實(shí)現(xiàn)了抽象方法test
                  Predicate<String> predicate = (s) -> s.length() > 0;

                  // 調(diào)用了test方法
                  
          // 輸出:true
                  System.out.println(predicate.test("landon"));

                  // default Predicate<T> negate() {return (t) -> !test(t);}
                  
          // 可以看到negate方法是一個(gè)默認(rèn)方法,其實(shí)現(xiàn)是返回一個(gè)!test的Predicate接口
                  
          // 輸出:false
                  System.out.println(predicate.negate().test("landon"));

                  // Objects是Java7引入的util中的一個(gè)類(lèi)
                  
          // public static boolean nonNull(Object obj) { return obj != null;}
                  Predicate<Boolean> nonNull = Objects::nonNull;
                  // public static boolean isNull(Object obj) {return obj == null;}
                  Predicate<Boolean> isNull = Objects::isNull;

                  // 輸出:true
                  System.out.println(nonNull.test(true));
                  // 輸出:false
                  System.out.println(nonNull.test(null));
                  // 輸出:false
                  System.out.println(isNull.test(false));
                  // 輸出:true
                  System.out.println(isNull.test(null));

                  // 這里看到,即使isEmpty方法是String的非靜態(tài)方法,這里也可以通過(guò)::進(jìn)行調(diào)用.
                  Predicate<String> isEmpty = String::isEmpty;
                  Predicate<String> isNotEmpty = isEmpty.negate();

                  // 輸出:true
                  System.out.println(isEmpty.test(""));
                  // 輸出:false
                  System.out.println(isEmpty.test("lambda"));
                  // 輸出:false
                  System.out.println(isNotEmpty.test(""));
                  // 輸出:true
                  System.out.println(isNotEmpty.test("lambda"));
              }

              /**
               * Function接口接收一個(gè)參數(shù),并返回單一的結(jié)果。默認(rèn)方法可以將多個(gè)函數(shù)串在一起(compse, andThen)
               * 
               * @FunctionalInterface public interface Function<T, R> {R apply(T t);
               
          */
              public void useFunction() {
                  // 實(shí)現(xiàn)apply接口
                  Function<String, Integer> toInteger = Integer::valueOf;
                  // default <V> Function<T, V> andThen(Function<? super R, ? extends V>
                  
          // after) {Objects.requireNonNull(after);return (T t) ->
                  
          // after.apply(apply(t));}

                  
          // andthen方法將apply的的輸出作為再一次apply的輸入,toInteger的apply輸出為Integer->
                  
          // 參數(shù)fucntion為Function<Integer,String>
                  Function<String, String> backToString = toInteger.andThen(String::valueOf);

                  // 輸出:123
                  System.out.println(backToString.apply("123"));
              }

              /**
               * Supplier接口產(chǎn)生一個(gè)給定類(lèi)型的結(jié)果。與Function不同的是,Supplier沒(méi)有輸入?yún)?shù)。
               * 
               * @FunctionalInterface public interface Supplier<T> {T get();}
               
          */
              public void useSupplier() {

                  // 編譯錯(cuò)誤: No enclosing instance of the type MethodConstructorRef is
                  
          // accessible in scope
                  
          // 因?yàn)镻erson屬于內(nèi)部類(lèi),其正常的初始化方式應(yīng)該是先初始化外部類(lèi),所以這里并非直接用::new,否則違背了內(nèi)部類(lèi)的規(guī)則
                  
          // Supplier<Person> personSupplier = Person::new;

                  Supplier<Person> personSupplier = new PersonSupplier();

                  System.out.println(personSupplier.get().getFirstName());
                  System.out.println(personSupplier.get().getLastName());

                  // 這里直接用::new的方式
                  Supplier<SupplierBean> beanSupplier = SupplierBean::new;

                  System.out.println(beanSupplier.get().a);
              }

              // 注:因?yàn)镻erson是MethodConstructorRef的內(nèi)部類(lèi),所以無(wú)法使用::new進(jìn)行初始化
              
          // 所以這里實(shí)現(xiàn)了Supplier接口,并采用內(nèi)部類(lèi)的方式進(jìn)行初始化
              private class PersonSupplier implements Supplier<Person> {
                  @Override
                  public Person get() {
                      MethodConstructorRef ref = new MethodConstructorRef();
                      return ref.new Person("java8", "tutorial");
                  }
              }

              /**
               * 測(cè)試Supplier接口而實(shí)現(xiàn)的一個(gè)JavaBean
               
          */
              private class SupplierBean {
                  public int a = 10086;
              }

              /**
               * Consumer代表了在一個(gè)輸入?yún)?shù)上需要進(jìn)行的操作
               * 
               * @FunctionalInterface public interface Consumer<T> {void accept(T t);
               
          */
              public void useConsumer() {
                  // 實(shí)現(xiàn)了accept方法,該方法為void
                  Consumer<Person> greeter = (p) -> System.out.println("Hello," + p.getFirstName());

                  // 首先實(shí)例化外部類(lèi)
                  MethodConstructorRef ref = new MethodConstructorRef();
                  greeter.accept(ref.new Person("Java8", "Lambda"));
              }

              /**
               * 使用加了@FunctionalInterface的Comparator. Java 8 為這個(gè)接口添加了不同的默認(rèn)方法
               
          */
              public void useNewComparator() {
                  // 實(shí)現(xiàn)compare接口
                  Comparator<Person> comparator = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());

                  // 首先實(shí)例化外部類(lèi)
                  MethodConstructorRef ref = new MethodConstructorRef();

                  Person p1 = ref.new Person("tracy", "mcgrady");
                  Person p2 = ref.new Person("kobe", "bryant");

                  System.out.println(comparator.compare(p1, p2));

                  // default Comparator<T> reversed() {return
                  
          // Collections.reverseOrder(this);}
                  
          // reversed方法為Comparator接口中的一個(gè)默認(rèn)方法.
                  System.out.println(comparator.reversed().compare(p1, p2));
              }

              /**
               * Optional不是一個(gè)函數(shù)式接口,而是一個(gè)精巧的工具接口,用來(lái)防止NullPointerEception產(chǎn)生。
               * Optional是一個(gè)簡(jiǎn)單的值容器,這個(gè)值可以是null,也可以是non-null。考慮到一個(gè)方法可能會(huì)返回一個(gè)non-null的值,
               * 也可能返回一個(gè)空值。為了不直接返回null,我們?cè)贘ava 8中就返回一個(gè)Optional。
               * 
               * public final class Optional<T>
               
          */
              public void useOptional() {
                  // public static <T> Optional<T> of(T value) { return new
                  
          // Optional<>(value);}
                  Optional<String> optional = Optional.of("landon");

                  // public boolean isPresent() {return value != null;}
                  System.out.println(optional.isPresent());
                  // public T get() {if (value == null) {throw new
                  
          // NoSuchElementException("No value present");}return value;}
                  System.out.println(optional.get());
                  // public T orElse(T other) {return value != null ? value : other;}
                  System.out.println(optional.orElse("mavs"));

                  // public void ifPresent(Consumer<? super T> consumer) {if (value !=
                  
          // null)consumer.accept(value);}
                  optional.ifPresent((s) -> System.out.println(s.charAt(0)));
              }

              public static void main(String[] args) {
                  LambdaBuildInFunctionalInterface buildInFunctionalInterface = new LambdaBuildInFunctionalInterface();

                  buildInFunctionalInterface.usePredicate();
                  buildInFunctionalInterface.useFunction();
                  buildInFunctionalInterface.useSupplier();
                  buildInFunctionalInterface.useConsumer();
                  buildInFunctionalInterface.useNewComparator();
                  buildInFunctionalInterface.useOptional();
              }
          }
          posted on 2014-11-17 15:45 landon 閱讀(5963) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Program
          主站蜘蛛池模板: 永川市| 抚顺市| 永登县| 福贡县| 静乐县| 平陆县| 康定县| 营口市| 玉田县| 抚州市| 甘孜县| 赤峰市| 普兰店市| 涟水县| 鞍山市| 阿拉善盟| 苏州市| 将乐县| 黄骅市| 澎湖县| 南漳县| 西乌珠穆沁旗| 历史| 南充市| 雷山县| 鄄城县| 石楼县| 阳高县| 宁乡县| 五大连池市| 西丰县| 马公市| 江西省| 左贡县| 建平县| 桐城市| 华坪县| 仲巴县| 饶河县| 太康县| 武隆县|