java都13了, 8的新特性你還不會用嗎

前言

java13都已經來了,不少同窗還停留在使用java5的東西。若是在平常開發中沒有使用上java8的一些新特性或者不會用。這篇文章對你可能有幫助。java

lambda表達式

介紹

lambda表達式是java8出的一種新的語法,經過匿名調用的方式使代碼更加優雅。web

函數式接口

介紹

爲了更友好的支持lambda表達式,在java8引入了函數式接口的概念。api

  • 「函數式接口」是指僅僅只包含一個抽象方法,可是能夠有多個非抽象方法(默認方法 default 修飾)的接口。
  • 「函數式接口」可使用@FunctionalInterface註解在接口上進行聲明 。因此你看到的接口上有這個註解的都是函數式接口。

在函數式接口中使用lambda表達式

先看下面一段代碼安全

@Test
    public void FunctionalInterface(){

        new Thread(new Runnable() {
            @Override
            public void run() {
                print();
            }
        });

        new Thread(
            () ->{print();}
        );

        new Thread(() -> print());

        new Thread(this::print);
    }

    public void print(){
        System.out.println("hello domain");
    }
複製代碼

上面的Runnable接口就是一個函數式接口, 第一種建立接口實例的方式使傳統的匿名內部類。其他三種方式是使用lambda建立的接口實例。第一種沒啥好說的,對其他三種的語法說明下。bash

  1. 第一種的語法格式是普通的完整的lambda語法,格式是: () -> {},小括號裏面的就是接口方法的傳參,大括號裏面的就是方法裏面的邏輯。能夠對照匿名實現接口的方式來看。
  2. 第二種方式,對比第一種少了大括號, 當大括號裏面的代碼是一句代碼時,能夠省略大括號。
  3. 第三種方式叫作lambda方法引用, 小括號,大括號都沒了,只剩下方法引用。 爲啥能夠這麼作, 由於大括號裏面的調用的方法入參和小括號裏面的入參是一致的。在例子中,小括號和大括號裏調用的方法都沒有參數,如是有參數會是這樣的:
@Test
    public void testFunctionalInterface(){
        WebService webService = this::print;
        webService.sayHi("domain");
    }

    public void print(String str){
        System.out.println("hi:"+str);
    }
複製代碼

上面例子能夠看到兩個點, 第一個就是上面說的有參數的lambda實踐,第二個是lambda表達式返回的確實是一個接口的實現實例。dom

方法引用

方法引用有三種方式,類名::方法對象::方法類名::new,最後這個語法是引用的構造方法。ide

Stream

介紹

stream 是java8對集合(不包括map)新增的一個api,配合lambda,更好的對集合進行各類操做。函數

使用

先建立一個list集合,使用stream來對它操做。ui

List<User> users = new ArrayList<>();
    users.add(new User("domain",18));
    users.add(new User("alex",19));
    users.add(new User("lily",20));
    users.add(new User("joy",21));
複製代碼

過濾(filter)

對集合中的數據進行過濾, 使用filter方法,好比我要拿到集合中年齡大於18的人:this

List<User> users = users.stream()
                .filter(new Predicate<User>() {
                    @Override
                    public boolean test(User user) {
                        return user.getAge() > 18;
                    }
                }).collect(Collectors.toList());
複製代碼

能夠看到,匿名內部實現的那一塊,能夠用lambda表達式來實現:

List<User> users = users.stream()
                .filter(user -> user.getAge() > 18).collect(Collectors.toList());

複製代碼

說明:user.stream來得到steam對象,filter進行過濾,collect來生成過濾後的對象,由於原對象不會改變。

類型轉換(map)

把集合類型和元素改變, 若是我要拿到集合中全部的姓名集合:

users.stream()
                .filter((user) -> user.getAge() > 18)
                .map(User::getName)
                .forEach(System.out::println);
複製代碼

這樣就是輸出全部的姓名。map以後能夠經過剛剛的collect轉爲一個新的集合對象。例子中沒有這樣作,是經過forEach將每一個元素輸出出來。

匹配(match)

尋找集合中的元素,進行匹配。

  • 任一匹配

如今我要知道集合中是否存在domain這個名字的人

boolean anyMatch = users.stream().anyMatch(user -> "domain".equals(user.getName()));
複製代碼
  • 全部匹配

集合中的名字是否都叫domain

boolean allMatch = users.stream().allMatch(user -> "domain".equals(user.getName()));
複製代碼
  • 都不匹配

集合中是否沒有domain姓名的人

boolean noneMatch = users.stream().noneMatch(user -> "domain".equals(user.getName()));
複製代碼

Optional

Optional是Java8提供的爲了解決null安全問題的一個API,講通俗點就是對數據的判空檢查。來看下面的例子

  • 我想要獲取user對象中的一個值,像下面這樣:
user = userService.getUser();
if (user == null) {
 throw new Excepiton("用戶不存在");
}

複製代碼

能夠看到爲了對數據的判空, 代碼變得很是冗長。Optional 提供了一套API 能使得這種判空檢查變得優雅些。

  • orElseThrow
User user = Optional.ofNullable(userService.getUser()).orElseThrow(() -> new Exception("用戶爲空爲空"));

複製代碼

上面經過調用orElseThrowuser爲空時,拋出對應異常。Optional.ofNullable是指定要操做的對象。

  • orElseGet
String name = Optional.ofNullable(user.getPerson().getName()).orElseGet(() -> "domain");

複製代碼

使用orElseGet來設置對象爲空時,返回的默認值。

相關文章
相關標籤/搜索