JDK1.8的新特性


JDK1.8的新特性

前言

以前大致了解過jdl1.8的一些新特性,長時間不用,慢慢忘記了,最近又撿起來看了下,並參考了一些博客,有些許新的收獲,特此記錄下。

參考博客: https://blog.csdn.net/chengwangbaiko/article/details/73433645

正文

關於1.8的一些新特性,會仔細研究過之后慢慢進行更新。

 1. 接口的擴展方法

在jdk1.8之前,接口中只允許有抽象方法,但是在1.8之后,接口中允許有一個非抽象的方法,但是必須使用default進行修飾,叫做擴展方法。

復制代碼
public interface UserService {

    void deleteUser(User user);
    
    default User showUser(User user){
        System.out.println("show User");
        user = Optional.ofNullable(user).orElse(new User());
        user.setName("這是經過擴展方法之后的user");
        return user;
    }
}
復制代碼

在我們實現接口之后,可以選擇對方法直接使用或者重寫。

2. 函數式接口,方法與構造方法的引用

函數式接口:接口中只有一個方法,可以對應一個lambda表達式。通過匿名內部類或者方法傳遞進行連接,調用接口即調用對應的方法。

復制代碼
@FunctionalInterface
public interface Converter<F,T> {
    T converter(F f);
}
//方法傳遞,使用的是Integer.valueOf()的方法
Converter<String ,Integer> converter = Integer::valueOf;
復制代碼

3. 其余的一些接口:

3.1:Predicate<T>接口:

  接口只有一個參數,返回boolean類型。該接口包含多種默認方法來將Predicate組合成其他復雜的邏輯(比如:與,或,非):

復制代碼
public static void main(String[] args) {
        //定義函數式接口,需要注意的是:Predicate接口指向方法的時候,指向的必須是返回值為boolean類型的方法。
        Predicate<String> predicate = s -> s.length() < 1; //定義函數式接口
        Predicate<String> predicate2 = Objects::nonNull;
        //Predicate接口的and方法,表示與。negative()表示的是否,or()表示的是或
        System.out.println(predicate2.test("ssss"));                //true
        System.out.println(predicate.and(predicate2).test("sss"));  //false
        System.out.println(predicate.or(predicate2).test("sss"));   //true
    }
復制代碼

3.2 Optional<T>類

  Optional<T>類,繼承Object,私有構造,是一個可能包含或不包含非空值的容器對象,如果一個值存在, isPresent()將返回true和get()將返回值。

  想要獲取對象可以直接使用一下幾種方法:

Optional<T>的靜態方法:
1. Optional.empty()-->返回一個空的Optional實例
2. Optional.of(T value) --> 返回一個具有Optional的當前非空值的optional實例,需要注意的是:這里傳的應該是非空值。如果可能為空,請用下面的
3. Optional.ofNullable(T value) -->返回一個具有Optional的當前值的optional實例,如果值為空,則返回一個空的Optional實例。

  關於Optional<T>的api,參考jdk1.8的API文檔。

  Optional<T>的一些應用實例:

1. 結合stream進行使用:后面詳細說
2. 單獨使用:Optional.ofNullable(user.getUserName()).orElse("hello,name is null").toString(); 
//解釋下:如果你數據庫查詢出的user的name字段未知,你要進行null判斷,如果未null,則顯示為“hello,name is null” 進行返回。toString是為了查詢到的name不是String的時候進行轉換。

3.2 Function接口、Supplier 接口、Consumer 接口等

  這些接口均是和lambda表達式進行配合,其中Function可以進行多個lambda的組合。

  (具體的詳情可以參見:jdk1.8的api文檔)

4. lamdba表達式的用法

4.1創建匿名內部類

  在1.8之前,我們創建匿名內部類的時候,是這樣的:

復制代碼
 Converter<String ,Integer> converter = new Converter<String, Integer>() {
        @Override
        public Integer converter(String s) {
            return Integer.parseInt(s);
        }
    };
復制代碼

  在1.8之后呢,我們可以這樣來創建

Converter<String ,Integer> converter = (f) -> {
        return Integer.valueOf(f);
    };

  更簡單的:如果你的方法體只有一句的話,你可以這樣來創建

Converter<String ,Integer> converter = (f) -> Integer.parseInt(f);

 4.2 lambda表達式和Stream接口對集合的操作《重點》

  1. Stream類似於流,單向,不可往復。可以對集合的所有元素進行篩選,過濾,修改等,但是只能對數據遍歷一次,如果需要第二次操作,必須繼續創建Stream流。

  2. Stream操作分為三個步驟:創建Stream--》中間操作--》最終操作。

4.2.1 構建流的幾種方法
 Stream<String> stream1 = Stream.of("aa", "bb", "cc"); //直接使用靜態方法,獲取指定值的順序排序流
 String [] strArray = {"a", "b", "c"};
 Stream<String> stream2 = Arrays.stream(strArray); //使用的Arrays類的stream方法
 List<String> list = Arrays.asList(strArray);
 Stream<String> stream3 = list.stream();//直接使用集合獲取流
4.2.2 常用的方法
1. foreach方法
復制代碼
public static void main(String[] args) {

        String[] arrs = {"hello","world","welcome","meet","you","aaa"};
        List<String> list = Arrays.asList(arrs);
        test1(list);
    }

    public static void test1(List list){
        list.stream().forEach(x -> System.out.println(x)); //拿到每個元素打印
        list.stream().forEach(System.out::println);  //如果只進行打印,可以使用方法的引用。
    }
復制代碼
2. 對數據進行過濾
 list.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);  //aaa,過濾開始元素為a的字符串。
3. 對數據進行排序
復制代碼
list.stream().filter((user) -> user.getName().startsWith("a")).sorted().forEach(System.out::println); 

 //需要特別注意的是:你對user進行排序,那么user類必須實現了Comparable<User>接口,並重寫compareTo方法,來定義比較方法才可以,否則會報無法轉換為Compare錯誤!

public class User implements Comparable<User>,Serializable {
  private Integer age;
  getter,setter省略。。。
  @Override
  public int compareTo(User user) {
   return user.getAge() - this.getAge() ;
  }
}
實現了Comparable接口之后,系統會知道如何進行排序比較。
復制代碼

需要注意的是:這里排序之后只是流中進行了排序,如果想要得到排序之后的集合,需要對流進行toArray操作,然后重新轉換成集合。

4. map操作

返回由給定函數應用於此流的元素的結果組成的流。 也就是我定義一個方法,對流中的每個元素進行操作。如果需要返回修改之后的list,則還需要toArray

復制代碼
list.stream().map((user -> {
            user.setName(user.getName().toUpperCase());
            return user;
        })).forEach(System.out::println);  //定義了一個Function<User,User>接口的匿名內部類,使用lambda表達式來實現。

 //寫的更加明顯一點如下:

 

Function<User,User> function = (user -> {
user.setName(user.getName().toUpperCase());
return user;
}); //Function接口的匿名內部類
list.stream().map(function).forEach(System.out::println);

 

復制代碼
5. count()操作:最終操作
long count = list.stream().filter((user) -> user.getName().startsWith("a")).count();
System.out.println("所有以a開頭用戶名字個數為: " + count);  // 所有以a開頭用戶名字個數為: 5

當使用最終操作之后,流就已經不存在了。

6. reduce操作
 Stream<String> stream1 = Stream.of("aa", "bb", "cc"); //直接使用靜態方法,獲取指定值的順序排序流
 stream1.reduce((s1,s2) ->s1 +"#" +s2).ifPresent(System.out::println);  //aa#bb#cc

操作的目的是:允許通過指定的函數來講stream中的多個元素規約為一個元素,最后得到的是一個Optional接口容器表示,如果想拿到值,需要get()來拿到。

7. 關於Stream的串行和並行
list.stream()-->即進行串行操作,單線程。時間長
list.parallelStream()-->並行操作,多線程同時進行。需要時間短

5. 時間表達式

復制代碼
LocalDate today = LocalDate.now(); //現在的日期
LocalDate tomorrow = today.plusDays(1); //今天之后的一天的日期
LocalTime time = LocalTime.of(10,10,10,358); //設定時間
LocalTime now = LocalTime.now(); //時間
LocalDateTime atDate = now.atDate(today);  //日期+時間
LocalDateTime dateTime = LocalDateTime.now(); //當前日期和時間
復制代碼


免責聲明!

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



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