Java 8 有哪些新特性


一、支持 lambda 表達式

例如:查詢學生信息,並打印

 List<Student> studentList = Student.findAllStudent();
        for(Student student:studentList){
            System.out.println(student);
        }

 使用 Lambda 的寫法

 Student.findAllStudent().stream().forEach(e->System.out.println(e));
 Student.findAllStudent().forEach(e->System.out.println(e));

 例如:創建一個線程

  Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+":重寫run 方法");
            }
        };

        Thread t1 = new Thread(runnable,"t1");
        t1.start();

 

 使用 Lambda 的寫法:

new Thread(()->System.out.println(Thread.currentThread().getName()+":重寫run 方法"),"t2").start();

 使用 Lambda 的前提:必須滿足是函數式接口,Runnable 就是一個函數式接口,用@FunctionalInterface 申明

 此外: Java8 提供了模板函數式的接口在包: Java.util.function 

01. 消費者接口

   

 02.函數接口

   

 

  03.判斷接口

  

 04.提供者接口

    

 除了上述接口,Java 就有的函數式接口Runnabkle Callable Comparator

 

 

 Lambda中使用的變量必須顯示的聲明為 final

方法引用:

Student.findAllStudent().stream().forEach(System.out::println);

 例如:

(Student s)->s.getSex(); 

Student::getSex

例如:輸出所有學生的姓名

Student.findAllStudent().stream().map(Student::getName).forEach(System.out::println);

  復合函數:

Function<Integer,Integer> f = x->x+4;
        Function<Integer,Integer> g = x->x*2;
        Function<Integer,Integer> k = f.andThen(g);
        System.out.println(k.apply(2));

解析:先將輸入 +4 ,將得到的結果 *2 ,組合使用函數

二、引入流

流在 java.util.stream.Stream,支持數據處理操作的源生成的元素序列。

filter :接收Lambda,從流中排除某些元素

map: 接受一個lambda,將元素轉換成其他形式或者提取信息

limit: 截斷流,使元素不超過指定數量

collect: 將流轉換為其他形式

 例如:查詢並打印年齡大於20的學生信息

 List<Student> students = Student.findAllStudent();
        List<Student> res = new ArrayList<>();
        for(Student student :students){
            if(student.getAge()>20){
                res.add(student);
            }
        }
        for(Student student: res){
            System.out.println(student);
        }

 

 使用流:

  Student.findAllStudent().stream()
              .filter(e->e.getAge()>20)
              .forEach(System.out::println);

 

 例如:查詢所有北京的學生,並按年齡升序輸出

  Student.findAllStudent().stream()
                .filter(e->e.getAddress().equals("北京"))
                .sorted(Comparator.comparing(Student::getAge))
                .forEach(System.out::println);

內部迭代與外部迭代:

for-each 結構是一個語法糖,背后的是 Iterator 還丑陋的東西。

流可以分為:中間操作、終端操作

中間操作: filter 、 sorted 等會返回另一個流。{filter、map、limit、sorted、distinct}

終端操作:終端操作會從流的流水線生成結果,結果不是流的值。 void 、list 等結果.{forEach、count、collect}

 例如:查詢集合中的偶數,去重復

 List<Integer> numbers = Arrays.asList(10,12,2,12,10,1,2);

      numbers.stream()
              .filter(e->e%2==0)
              .distinct()
              .forEach(System.out::println);

例如:查詢集合中前 3 個數據

numbers.stream()
              .limit(3)
              .forEach(System.out::println);

例如:忽略集合中前3個數據

numbers.stream()
              .skip(3)
              .forEach(System.out::println);

例如:查詢學生信息中地址,去重

 Student.findAllStudent().stream()
             .map(e->e.getAddress())
             .distinct()
             .forEach(System.out::println);

 

 例如:將【“Hello”,“World”】 處理為:【“H”,"e","l","o"...】

 List<String> str = Arrays.asList("Hello","World");
     List<String[]> res = str.stream()
             .map(e->e.split(""))
             .distinct()
             .collect(toList());

返回的是2個String 數組,而想要的結果是一個string 數組

 List<String> res = str.stream()
           .map(e->e.split(""))
           .flatMap(Arrays::stream)
           .distinct()
           .collect(toList());
   System.out.println(res);

flatMap : 把流中的每個值都換成另一個流,然后把所有的流連接起來形成一個流。

例如:判斷學生中是否所有的年齡都小於20

   boolean res =Student.findAllStudent().stream()
           .allMatch(e->e.getAge()<20);
   System.out.println(res);

例如:判斷學生中是否有成都的

 boolean res =Student.findAllStudent().stream()
           .anyMatch(e->e.getAddress()=="成都");
   System.out.println(res);

規約:求學生的年齡和

int sum = Student.findAllStudent().stream()
                .map(Student::getAge)
                .reduce(0,(e1,e2)->e1+e2);
        System.out.println(sum);
 int sum = Student.findAllStudent().stream()
                .map(Student::getAge)
                .reduce(0,Integer::sum);
        System.out.println(sum);

無初始值-規約:

  Optional<Integer> sum = Student.findAllStudent().stream()
                .map(Student::getAge)
                .reduce((e1,e2)->e1+e2);
        System.out.println(sum);

例如:返回所有學生姓名字符串,按字母順序排列

 String str = Student.findAllStudent().stream()
               .map(Student::getName)
               .distinct()
               .sorted()
               .reduce("",(e1,e2)->e1+e2);
       System.out.println(str);

例如:查找年齡最小的學習年齡

 Optional<Integer> min = Student.findAllStudent().stream()
                .map(Student::getAge)
                .reduce(Integer::min);
        System.out.println(min);

使用 groupingBy 按城市分組查詢:

Map<String,List<Student>> map = Student.findAllStudent().stream()
                .collect(groupingBy(Student::getAddress));


        for(Map.Entry<String,List<Student>> entry: map.entrySet()){
            System.out.println(entry.getKey()+","+entry.getValue());
        }

 收集器的 Joining 匯總

joining 會把流中每一個對象應用 toString 方法得到的字符串連接成一個字符串。

例如:將城市去重以字符串返回

  String str = Student.findAllStudent().stream()
             .map(Student::getAddress)
             .distinct()
             .collect(joining());
     System.out.println(str);

 

 

 String str = Student.findAllStudent().stream()
             .map(Student::getAddress)
             .distinct()
             .collect(joining(","));
     System.out.println(str);

 

 例如:將學生按年齡分組

 Map<Integer,List<Student>> map = Student.findAllStudent().stream()
                .collect(groupingBy(Student::getAge));

        for(Map.Entry<Integer,List<Student>> entry:map.entrySet()){
            System.out.println(entry.getKey()+","+entry.getValue());
        }

 

 使用 counting 

計算每個年齡組人的個數

Map<Integer,Long> map = Student.findAllStudent().stream()
                .collect(groupingBy(Student::getAge,counting()));

        for(Map.Entry<Integer,Long> entry:map.entrySet()){
            System.out.println(entry.getKey()+","+entry.getValue());
        }

 

並行流

使用 parallelStream 方法把集合轉換為並行流

打印學生信息

 Student.findAllStudent().parallelStream().forEach(System.out::println);

輸出學生姓名

 String str = Student.findAllStudent().parallelStream()
               .map(Student::getName)
               .collect(joining(","));
       System.out.println(str);

分支/合並框架(ForkJoinPool)

目的:以遞歸方式將可以並行的任務拆分成更小的任務,然后將每個子任務的結果合並起來生成整體的結果

繼承 RecursiveTask<T>

Spliterator : 可分迭代器,可並行遍歷數據源中的數據

三、默認方法

問題:接口中的方法,子類必須實現。由於 java8 接口增加許多,為了不帶來更多的問題,添加新的機制

1.java8 允許在接口內聲明靜態方法

2.java8 引入一個新的功能 ,默認方法。接口能夠提供具體的實現

四、Optional 取代 null

java.util.Optional<T>  

當變量存在時,Optional 對對象簡單的封裝,當變量不存在時,缺失的值被建模成 kong  的optional 對象。由 Optional.empty() 返回

五、CompleteableFuture 組合式異步編程

Future 接口,java5引入。提供了異步操作。

六、新的日期與時間 API

java.util.Date 、 java.utlo.Calender 設計的缺陷

缺陷: java.util.Date  無法表示日期,只能以毫秒精確時間。年份的起始選擇的是 1900 年,月份從 0 開始。

缺陷:java.util.Calendar 月份呢依然是從 0開始,取消 1900 年開始。

新的時間: java.time 包

1.獲取當前日期

 LocalDate today = LocalDate.now();
 System.out.println(today);

 

 2.獲取指定日期

 LocalDate localDate = LocalDate.of(2018,4,5);

        System.out.println(localDate.getDayOfWeek());

        System.out.println(localDate.getDayOfMonth());

        System.out.println(localDate.getDayOfYear());

 

 3.指定時間

LocalTime localTime = LocalTime.of(13,14,50);

        System.out.println(localTime.getHour());

        System.out.println(localTime.getMinute());

        System.out.println(localTime.getSecond());

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM