1. 程式人生 > >Jdk1.8新特性

Jdk1.8新特性

  1. Lambda表示式:Lambda 允許把函式作為一個方法的引數(函式作為引數傳遞進方法中)。可以使程式碼變的更加簡潔緊湊。

      Lambda表示式的實質其實還是匿名內部類,而匿名內部類在訪問外部區域性變數時,要求變數必須宣告為final!不過我們在使用Lambda表示式時無需宣告final,這並不是說違反了匿名內部類的規則,因為Lambda底層會隱式的把變數設定為final,在後續的操作中,一定不能修改該變數:

基本語法:

(引數列表) -> {程式碼塊}

需要注意:

  • 引數型別可省略,編譯器可以自己推斷

  • 如果只有一個引數,圓括號可以省略

  • 程式碼塊如果只是一行程式碼,大括號也可以省略

  • 如果程式碼塊是一行,且是有結果的表示式,return可以省略

注意:事實上,把Lambda表示式可以看做是匿名內部類的一種簡寫方式。當然,前提是這個匿名內部類對應的必須是介面,而且介面中必須只有一個函式!Lambda表示式就是直接編寫函式的:引數列表、程式碼體、返回值等資訊,用函式來代替完整的匿名內部類

用法示例

 @Test
     public void lambdaDemo(){
          //準備一個集合
          List<Integer> list = Arrays.asList(1, 3, 5, 3, 1, 3, 67, 8);

          // 對集合進行Jdk1.7寫法,倒序和正序
          Collections.sort(list,new Comparator<Integer>() {
               @Override
               public int compare(Integer o1, Integer o2) {
                    return o1 - o2;
               }
          });
          System.out.println(list);// [-15, 5, 10, 20, 25]
          // Jdk1.8寫法,引數列表的資料型別可省略: lambda表示式做排序
          Collections.sort(list,(Integer a,Integer b)->{ return b-a; });
          System.out.println(list);
          // Jdk8寫法 簡潔版
          // 因為程式碼塊是一個有返回值的表示式,可以省略大括號以及return
          Collections.sort(list,(a,b)->a-b);
          System.out.println(list);


     }

示例2:單個引數

還以剛才的集合為例,現在我們想要遍歷集合中的元素,並且列印。

jdk1.8給集合添加了一個方法:foreach() ,接收一個對元素進行操作的函式:


          // JDK1.7遍歷並列印集合
          for (Integer i : list) {
               System.out.println(i);
          }
          // JDK1.8遍歷並列印集合,因為只有一個引數,所以我們可以省略小括號:
          list.forEach(i -> System.out.println(i));

Lambda表示式的實質其實還是匿名內部類,所以我們其實可以把Lambda表示式賦值給某個變數。

  • Lambda表示式是介面的匿名內部類的簡寫形式

  • 介面必須滿足:內部只有一個函式

  1. 其實這樣的介面,我們稱為函式式介面,我們學過的RunnableComparator都是函式式介面的典型代表。但是在實踐中,函式介面是非常脆弱的,只要有人在接口裡新增多一個方法,那麼這個介面就不是函式介面了,就會導致編譯失敗。Java 8提供了一個特殊的註解@FunctionalInterface來克服上面提到的脆弱性並且顯示地表明函式介面。而且jdk8版本中,對很多已經存在的介面都添加了@FunctionalInterface註解,例如Runnable介面:

另外,Jdk8預設提供了一些函式式介面供我們使用:

  • Function型別介面
@FunctionalInterface
public interface Function<T, R> {
	// 接收一個引數T,返回一個結果R
    R apply(T t);
}

Function代表的是有引數,有返回值的函式。還有很多類似的Function介面:

介面名 描述
BiFunction<T,U,R> 接收兩個T和U型別的引數,並且返回R型別結果的函式
DoubleFunction<R> 接收double型別引數,並且返回R型別結果的函式
IntFunction<R> 接收int型別引數,並且返回R型別結果的函式
LongFunction<R> 接收long型別引數,並且返回R型別結果的函式
ToDoubleFunction<T> 接收T型別引數,並且返回double型別結果
ToIntFunction<T> 接收T型別引數,並且返回int型別結果
ToLongFunction<T> 接收T型別引數,並且返回long型別結果
DoubleToIntFunction 接收double型別引數,返回int型別結果
DoubleToLongFunction 接收double型別引數,返回long型別結果
  • Consumer系列

@FunctionalInterface
public interface Consumer<T> {
	// 接收T型別引數,不返回結果
    void accept(T t);
}
  • Predicate系列

@FunctionalInterface
public interface Predicate<T> {
	// 接收T型別引數,返回boolean型別結果
    boolean test(T t);
}
  • Supplier系列
@FunctionalInterface
public interface Supplier<T> {
	// 無需引數,返回一個T型別結果
    T get();
}

Streams流

新增  java.util.Stream  API

把一個集合變成一個流,  Lists.stream()

案例一、 對集合進行排序然後去除所有的偶數再把所有數*2

這些個所有操作只經過一次遍歷, 

 @Test
     public void streamLambdaDemo03() {
          // 對集合進行排序然後去除所有的偶數再把所有數*2
          List<Integer> list = Arrays.asList(1, 3, 5, 3, 1, 3, 67, 8);
          //過濾偶數(傳入一個引數然後返回一個引數)
          list.stream().filter(i-> i%2!=0)//  列印  1,3,5,3,1,3,67
                   //把集合中的每個資料用函式處理
                    .map(i->i*2)   // 列印  2,6,10,6,2,6,134
                   //排序
                   .sorted((i1,i2)->i1-i2)  //  列印  2,2,6,6,6,10,134
                         //JDK1.8遍歷並列印集合
                         .forEach(i-> System.out.println(i));


                   list.stream()
                   //加上parallel()方法還可以使這個流多執行緒處理極大的提高效率
                   .parallel()
                   .filter(i -> { System.out.println(Thread.currentThread().getName());
                    return i % 2 != 0; })//  列印  1,3,5,3,1,3,67
                   //把集合中的每個資料用函式處理
                   .map(i -> {
                        System.out.println(Thread.currentThread().getName());
                        return i * 2;
                   })   // 列印  2,6,10,6,2,6,134
                   //排序
                   .sorted((i1, i2) -> {
                        System.out.println(Thread.currentThread().getName());
                        return i1 - i2;
                   })  //  列印  2,2,6,6,6,10,134
                   //JDK1.8遍歷並列印集合
                   .forEach(i -> System.out.println(i));



     }