JAVA打怪之路 - JAVA 8 新特性

JAVA 8 新特性

前言

近些年來,JAVA技術發展受到嚴峻的挑戰,新型的Python語言,Go語言,機器學習語言都在向JAVA的霸主地位發起挑戰,誰能夠在這個時代更高效的完成項目開發迭代,更好的適應技術的發展,誰就能逐步佔領市場。JAVA被收購後,其開發團隊不斷尋求新的技術理念思想,融入新的概念,從而使得JAVA近來的更新變得更爲頻繁,也增加了許多新的技術特點,來迎接新的技術開發特性,維護自己的霸主地位。

下面就是比較詳細的JAVA 8 新特性展示圖
在這裏插入圖片描述

一、Lambda表達式

“->” , 該操作符被稱爲 Lambda 操作符或箭頭操作符。它將 Lambda 分爲兩個部分:
左邊:lambda形參列表的參數類型可以省略(類型推斷);如果lambda形參列表只有一個參數,其一對()也可以省略。
右邊:lambda體應該使用一對{}包裹;如果lambda體只有一條執行語句(可能是return語句),省略這一對{}和return關鍵字。
在這裏插入圖片描述
在這裏插入圖片描述
Lambda 表達式:語法
在這裏插入圖片描述
在這裏插入圖片描述
二、函數式(Functional)接口
在這裏插入圖片描述
Java 內置四大核心函數式接口:
在這裏插入圖片描述
其他接口:
在這裏插入圖片描述
三、方法引用與構造器引用
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

四、強大的Stream API
在這裏插入圖片描述

注意:

① Stream 自己不會存儲元素。

② Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。

③ Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。

Stream 的操作三個步驟:
在這裏插入圖片描述

① 創建Stream的方式
在這裏插入圖片描述
在這裏插入圖片描述
② Stream 的中間操作

在這裏插入圖片描述
在這裏插入圖片描述
③ Stream 的終止操作
在這裏插入圖片描述
在這裏插入圖片描述

Collectors工具類
在這裏插入圖片描述
在這裏插入圖片描述

五、Optional類
在這裏插入圖片描述
附1:Optional使用代碼示例:

public class OptionalTest {
/*
Optional.of(T t) : 創建一個 Optional 實例,t必須非空;
Optional.empty() : 創建一個空的 Optional 實例
Optional.ofNullable(T t):t可以爲null
 */
    @Test
    public void test1(){
         Girl girl = new Girl();
        girl = null;
        //of(T t):保證t是非空的
        Optional<Girl> optionalGirl = Optional.of(girl);
    }
    @Test
    public void test2(){
        Girl girl = new Girl();
//        girl = null;
        //ofNullable(T t):t可以爲null
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println(optionalGirl);
        //orElse(T t1):如果單前的Optional內部封裝的t是非空的,則返回內部的t.
        //如果內部的t是空的,則返回orElse()方法中的參數t1.
        Girl girl1 = optionalGirl.orElse(new Girl("趙麗穎"));
        System.out.println(girl1);
    }
    public String getGirlName(Boy boy){
        return boy.getGirl().getName();
    }
    @Test
    public void test3(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName(boy);
        System.out.println(girlName);
    }
    //優化以後的getGirlName():
    public String getGirlName1(Boy boy){
        if(boy != null){
            Girl girl = boy.getGirl();
            if(girl != null){
                return girl.getName();
            }
        }
        return null;
    }
    @Test
    public void test4(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName1(boy);
        System.out.println(girlName);
    }
    //使用Optional類的getGirlName():
    public String getGirlName2(Boy boy){
        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        //此時的boy1一定非空
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪麗熱巴")));
        Girl girl = boy1.getGirl();
        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        //girl1一定非空
        Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
        return girl1.getName();
    }
    @Test
    public void test5(){
        Boy boy = null;
        boy = new Boy();
        boy = new Boy(new Girl("蒼老師"));
        String girlName = getGirlName2(boy);
        System.out.println(girlName);
    }
}

附2:Lambda表達式的使用

public class LambdaTest1 {
    //語法格式一:無參,無返回值
    @Test
    public void test1(){
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我愛北京天安門");
            }
        };
        r1.run();
        System.out.println("***********************");
        Runnable r2 = () -> {
            System.out.println("我愛北京故宮");
        };
        r2.run();
    }
    //語法格式二:Lambda 需要一個參數,但是沒有返回值。
    @Test
    public void test2(){
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("謊言和誓言的區別是什麼?");
        System.out.println("*******************");
        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");
    }

    //語法格式三:數據類型可以省略,因爲可由編譯器推斷得出,稱爲“類型推斷”
    @Test
    public void test3(){
        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");
        System.out.println("*******************");
        Consumer<String> con2 = (s) -> {
            System.out.println(s);
        };
        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }
    @Test
    public void test4(){
        ArrayList<String> list = new ArrayList<>();//類型推斷
        int[] arr = {1,2,3};//類型推斷
    }
    //語法格式四:Lambda 若只需要一個參數時,參數的小括號可以省略
    @Test
    public void test5(){
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");
        System.out.println("*******************");
        Consumer<String> con2 = s -> {
            System.out.println(s);
        };
        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }

    //語法格式五:Lambda 需要兩個或以上的參數,多條執行語句,並且可以有返回值
    @Test
    public void test6(){
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };
        System.out.println(com1.compare(12,21));
        System.out.println("*****************************");
        Comparator<Integer> com2 = (o1,o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
       System.out.println(com2.compare(12,6));
    }
    //語法格式六:當 Lambda 體只有一條語句時,return 與大括號若有,都可以省略
    @Test
    public void test7(){
        Comparator<Integer> com1 = (o1,o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(com1.compare(12,6));
        System.out.println("*****************************");
        Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
        System.out.println(com2.compare(12,21));
    }
    @Test
    public void test8(){
        Consumer<String> con1 = s -> {
            System.out.println(s);
        };
        con1.accept("一個是聽得人當真了,一個是說的人當真了");
        System.out.println("*****************************");
        Consumer<String> con2 = s -> System.out.println(s);
        con2.accept("一個是聽得人當真了,一個是說的人當真了");
    }
}

附3:java內置的4大核心函數式接口

public class LambdaTest2 {
    @Test
    public void test1(){
        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("學習太累了,去天上人間買了瓶礦泉水,價格爲:" + aDouble);
            }
        });
        System.out.println("********************");
        happyTime(400,money -> System.out.println("學習太累了,去天上人間喝了口水,價格爲:" + money));
    }

    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }
    @Test
    public void test2(){
        List<String> list = Arrays.asList("北京","南京","天津","東京","西京","普京");
        List<String> filterStrs = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });
        System.out.println(filterStrs);
        List<String> filterStrs1 = filterString(list,s -> s.contains("京"));
        System.out.println(filterStrs1);
    }
    //根據給定的規則,過濾集合中的字符串。此規則由Predicate的方法決定
    public List<String> filterString(List<String> list, Predicate<String> pre){
        ArrayList<String> filterList = new ArrayList<>();
        for(String s : list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }
        return filterList;
    }
}

附4:構造器和數組引用

public class ConstructorRefTest {
   //構造器引用
    //Supplier中的T get()
    //Employee的空參構造器:Employee()
    @Test
    public void test1(){
        Supplier<Employee> sup = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println("*******************");
        Supplier<Employee>  sup1 = () -> new Employee();
        System.out.println(sup1.get());
        System.out.println("*******************");
        Supplier<Employee>  sup2 = Employee :: new;
        System.out.println(sup2.get());
    }

   //Function中的R apply(T t)
    @Test
    public void test2(){
        Function<Integer,Employee> func1 = id -> new Employee(id);
        Employee employee = func1.apply(1001);
        System.out.println(employee);
        System.out.println("*******************");
        Function<Integer,Employee> func2 = Employee :: new;
        Employee employee1 = func2.apply(1002);
        System.out.println(employee1);
    }
   //BiFunction中的R apply(T t,U u)
    @Test
    public void test3(){
        BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
        System.out.println(func1.apply(1001,"Tom"));
        System.out.println("*******************");
        BiFunction<Integer,String,Employee> func2 = Employee :: new;
        System.out.println(func2.apply(1002,"Tom"));
    }
   //數組引用
    //Function中的R apply(T t)
    @Test
    public void test4(){
        Function<Integer,String[]> func1 = length -> new String[length];
        String[] arr1 = func1.apply(5);
        System.out.println(Arrays.toString(arr1));
        System.out.println("*******************");
        Function<Integer,String[]> func2 = String[] :: new;
        String[] arr2 = func2.apply(10);
        System.out.println(Arrays.toString(arr2));
    }
}

附5:方法引用

public class MethodRefTest {
   // 情況一:對象 :: 實例方法
   //Consumer中的void accept(T t)
   //PrintStream中的void println(T t)
   @Test
   public void test1() {
      Consumer<String> con1 = str -> System.out.println(str);
      con1.accept("北京");

      System.out.println("*******************");
      PrintStream ps = System.out;
      Consumer<String> con2 = ps::println;
      con2.accept("beijing");
   }
   
   //Supplier中的T get()
   //Employee中的String getName()
   @Test
   public void test2() {
      Employee emp = new Employee(1001,"Tom",23,5600);
      Supplier<String> sup1 = () -> emp.getName();
      System.out.println(sup1.get());
      System.out.println("*******************");
      Supplier<String> sup2 = emp::getName;
      System.out.println(sup2.get());

   }

   // 情況二:類 :: 靜態方法
   //Comparator中的int compare(T t1,T t2)
   //Integer中的int compare(T t1,T t2)
   @Test
   public void test3() {
      Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
      System.out.println(com1.compare(12,21));
      System.out.println("*******************");
      Comparator<Integer> com2 = Integer::compare;
      System.out.println(com2.compare(12,3));

   }
   
   //Function中的R apply(T t)
   //Math中的Long round(Double d)
   @Test
   public void test4() {
      Function<Double,Long> func = new Function<Double, Long>() {
         @Override
         public Long apply(Double d) {
            return Math.round(d);
         }
      };
      System.out.println("*******************");
      Function<Double,Long> func1 = d -> Math.round(d);
      System.out.println(func1.apply(12.3));
      System.out.println("*******************");
      Function<Double,Long> func2 = Math::round;
      System.out.println(func2.apply(12.6));
   }

   // 情況三:類 :: 實例方法  (有難度)
   // Comparator中的int comapre(T t1,T t2)
   // String中的int t1.compareTo(t2)
   @Test
   public void test5() {
      Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
      System.out.println(com1.compare("abc","abd"));
      System.out.println("*******************");
      Comparator<String> com2 = String :: compareTo;
      System.out.println(com2.compare("abd","abm"));
   }

   //BiPredicate中的boolean test(T t1, T t2);
   //String中的boolean t1.equals(t2)
   @Test
   public void test6() {
      BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
      System.out.println(pre1.test("abc","abc"));
      System.out.println("*******************");
      BiPredicate<String,String> pre2 = String :: equals;
      System.out.println(pre2.test("abc","abd"));
   }
   
   // Function中的R apply(T t)
   // Employee中的String getName();
   @Test
   public void test7() {
      Employee employee = new Employee(1001, "Jerry", 23, 6000);
      Function<Employee,String> func1 = e -> e.getName();
      System.out.println(func1.apply(employee));
      System.out.println("*******************");
      Function<Employee,String> func2 = Employee::getName;
      System.out.println(func2.apply(employee));
   }
}

附6:Stream的實例化四種方式

public class StreamAPITest {
    //創建 Stream方式一:通過集合
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();
//        default Stream<E> stream() : 返回一個順序流
        Stream<Employee> stream = employees.stream();
//        default Stream<E> parallelStream() : 返回一個並行流
        Stream<Employee> parallelStream = employees.parallelStream();
    }

    //創建 Stream方式二:通過數組
    @Test
    public void test2(){
        int[] arr = new int[]{1,2,3,4,5,6};
        //調用Arrays類的static <T> Stream<T> stream(T[] array): 返回一個流
        IntStream stream = Arrays.stream(arr);
        Employee e1 = new Employee(1001,"Tom");
        Employee e2 = new Employee(1002,"Jerry");
        Employee[] arr1 = new Employee[]{e1,e2};
        Stream<Employee> stream1 = Arrays.stream(arr1);
    }
    //創建 Stream方式三:通過Stream的of()
    @Test
    public void test3(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
    }

    //創建 Stream方式四:創建無限流
    @Test
    public void test4(){
//      迭代
//      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        //遍歷前10個偶數
        Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
//      生成
//      public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章