中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java8新特性lambda表達式的語法是什么

發布時間:2023-03-13 13:58:04 來源:億速云 閱讀:107 作者:iii 欄目:開發技術

這篇“java8新特性lambda表達式的語法是什么”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“java8新特性lambda表達式的語法是什么”文章吧。

定義

jdk8發布新特性中,lambda是一大亮點之一。lambda表達式能夠簡化我們對數據的操作,減少代碼量,大大提升我們的開發效率。

Lambda 表達式”(lambda expression)是一個匿名函數,Lambda表達式基于數學中的λ演算得名,直接對應于其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。

Lambda表達式可以表示閉包。如果你之前了解scala和js函數式編程,將會更加快速上手和學習java8的lambda新特性。

lambda表達式的語法

Lambda表達式在Java8中引入了一個新的語法操作符號,即:->,它將Lambda表達式分為兩部分。

左側

  • Lambda表達式左側為入參參數。

右側

  • Lambada表示式的右側表示執行的功能。

總結就是:

(parameters) -> expression
或
(parameters) ->{ statements; }

以下是Lambda表達式幾種語法格式:

1.無參,無返回值,典型的一個例子是Runnable匿名內部類的使用。

// java 8之前的寫法
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " >---Lambda");
    }
};
// 使用lambda的寫法
Runnable r = () -> System.out.println(Thread.currentThread().getName() + " >---Lambda");

2.一個參數的使用

// java 8 之前的寫法
Consumer<String> consumer = new Consumer<String>() {
     @Override
    public void accept(String s) {
         System.out.println(s);
       }
    };
 // Lambda表達式的寫法
Consumer<String> consumer = (par)->System.out.println(par);
consumer.accept("xixi");
一個參數的小括號可以省略,簡化如下:
Consumer<String> consumer = par->System.out.println(par);

3.兩個參數的使用

// java 8之前的寫法
Comparator<Integer> comparator = new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
       return o1.compareTo(o2);
     }
 };
 // 使用Lambda表達式的方法 ,當只有一條語句的時候,大括號和return都可以省略
  Comparator<Integer> comparator=(x,y) -> x.compareTo(y);

觀察上面的代碼后,我們發現使用Lambda表達式,在Lambda表達式中并沒有指定入參的參數類型。這個編譯和運行沒有報錯,這個是怎么判斷出來的呢?

很簡單是類型推斷的作用,java8中有個很大的變化,就是類型推斷,簡單來說javac在編譯代碼時候,會根據程序的上下文來推斷出Lambda表達式參數類型。

例如上文中的下面這個代碼:

Comparator<Integer> comparator=(x,y) -> x.compareTo(y);

這里在編譯的時候,在執行x.compareTo(y)的時候根據類型推斷,因為這個接口定義數據的泛型是Intger,所以根據類型推斷會自動調用Integer.compareTo方法。

為理解lambda表達式的作用,以及簡化我們開發。這兒將會舉個小小的例子。

需求

王小明所在的公司,每一個月都會進行薪資財務報表,王小明每一個月都會自己對員工們的薪資做統計,以了解公司財務支出和訂單提成等需求。常常有做訂單提成排名和總工資排名的這樣的一個需求。

我們將定義以下類,來完成王小明的統計需求。

基本員工類

package com.codegeek.lambda;
import lombok.*;

@Setter
@Getter
@NoArgsConstructor
@ToString
public class Employee {
    /**
     * 員工姓名
     */
    private String name;
    /**
     * 員工年齡
     */
    private int age;
    /**
     * 基本薪水
     */
    private double basicSalary;

    /**
     * 訂單成交總額
     */
    private double dealTotalPrice;

    public Employee(String name, int age, double basicSalary,double dealTotalPrice) {
        this.name = name;
        this.age = age;
        this.basicSalary = basicSalary;
        this.dealTotalPrice = dealTotalPrice;
    }

    /**
     * 員工總薪資
     *
     * @return Double
     */
    public Double getTotalSalary() {
        return this.basicSalary + this.dealTotalPrice * 0.04;
    }
}

現在假設在A部門有,青龍,白虎,朱雀,玄武 四個部門人員。下面是他們上個月基本薪資的情況。

Employee qingLong = new Employee("青龍", 25, 5500, 7500);
Employee baiHu = new Employee("白虎", 27, 5000, 9000);
Employee zhuQue = new Employee("朱雀", 22, 3800, 4500);
Employee xuanWu = new Employee("玄武", 24, 3300, 3300);
List<Employee> employees = Arrays.asList(qingLong, baiHu, zhuQue, xuanWu);

現在有個統計的需求是,按員工年齡從小到大排列,并獲取員工姓名列表。讓我們分別使用Lambda表達式和java8之前的做法。

java8之前通常的做法

// 員工列表先進行排序
employees.sort(new Comparator<Employee>() {
  @Override
  public int compare(Employee o1, Employee o2) {
     Integer age1 = o1.getAge();
     Integer age2 = o2.getAge();
     return age1.compareTo(age2);
 }
});
// 遍歷排序后的列表并輸出員工姓名
  for (Employee employee : employees) {
    System.out.println(employee.getName());
 }

使用Lambda的做法

employees.stream().sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge()))
.forEach(o -> System.out.println(o.getName()));

看到這里我們一定知道Lambda表達式使用的方便,確實減少了很多代碼的使用。

函數式接口

只包含一個抽象方法的接口,稱為函數式接口。

使用Lambda表達式創建該對象接口的對象,如果Lambda拋出一個受檢異常,通常需要在目標接口使用@FunctionalInterface注解,來聲明標記了該注解的接口是一個函數式接口。

例如:

Consumer<String> consumer = par->System.out.println(par);

就是一個典型的消費型函數式接口。

java8新特性lambda表達式的語法是什么

注意觀察該接口的源代碼,只包含一個抽象的方法的接口是函數式接口,下面andThen是一個默認方法,并不屬于抽象方法。不要被迷惑了。

內建函數式的接口

jdk8中默認定義了很多函數式接口,主要使用的有下面四個。

函數式接口參數類型返回類型使用說明
Consumer<T> 消費型接口Tvoid對類型T的數據進行操作,抽象方法 void accept(T t)
Supplier 供給型接口T返回類型T的對象,抽象方法 T get();
Function<T,R> 函數型接口TR對類型T對象進行操作,返回類型R的對象,抽象方法R apply(T t)
Predicate<T> 斷言型接口Tbolean對類型T對象進行操作,返回類型boolean,抽象方法boolean test(T t)

四大函數式接口的使用

public class FourFunctionsTest {

    // 消費式接口
    @Test
    public void testConsumer() {
        Consumer<Integer> consumer = x -> System.out.println(x);
        consumer.accept(1);
    }

    // 供給式接口
    @Test
    public void testSupplier() {
        Supplier<String> supplier = () -> {
            StringBuffer sb = new StringBuffer();
            return sb.append("我").append(520).append("you").toString();
        };
        System.out.println(supplier.get());
    }

    // 斷言式接口
    @Test
    public void testPredicate() {
        Predicate<Long> predicate = x -> x == 1L;
        System.out.println(predicate.test(2L));
    }

    // 函數式接口
    @Test
    public void testFunction() {
        Function<Integer, Boolean> function = x -> x > 3;
        System.out.println(function.apply(4));
    }
}

自定義函數式接口

上面我們舉例A部門的四個員工,找出工資大于5000的員工。

// 使用策略式接口
@FunctionalInterface // 函數式接口(檢查)只能有一個抽象方法
public interface MyFilter<T> {
    /**
     * 獲取指定想要的employee對象
     *
     * @param t
     * @return
     */
    boolean getWant(T t);
}
    /**
     * 策略設計模式
     */
public List<Employee> needEmployee(List<Employee> employeeList, MyFilter<Employee> filter) {
   List<Employee> employees = new ArrayList<>();
     for (Employee employee : employeeList) {
        if (filter.getWant(employee)) {
            employees.add(employee);
        }
     }
      return employees;
 }
// 匿名內部類
List<Employee> employees1 = needEmployee(employees, new MyFilter<Employee>() {
  @Override
  public boolean getWant(Employee employee) {
      return employee.getTotalSalary() >= 5000;
   }
});
// 使用策略者設計模式Lambda簡化
needEmployee(employees, employee -> mployee.getTotalSalary() >= 5000);

看了上面代碼,如果還想簡化怎么做呢?這里可以使用java 8的Stream API可以大大簡化以上繁多的代碼。

employees.stream().filter(e -> e.getTotalSalary() > 5000d).map(Employee::getName).forEach(System.out::println);

看到這兒,可能剛剛入門的同學會懵逼,因為上面用了Stream相關的API以及(Employee::getName)中::表示什么含義呢?別著急,慢慢往下看。

方法引用

使用操作符::將方法名和對象或者類的名字分隔開,組合有以下三種。

  • 對象::實例方法名

  • 類::靜態方法

  • 類::實例方法

常見的x-> System.out.println() 等同于System.out::println。 

注意:

  • Lambda 體中調用方法的參數列表與返回值類型,要與函數式接口抽象方法的該函數列表和返回值類型保持一致。

  • 若Lambda參數列表中的第一個參數是實例方法的調用者,而第二個參數是實例方法的參數時。可以使用 ClassName :: method

說起來比較抽象,請看下面的例子。

// 對象::實例方法
    @Test
    public void testConsumer() {
        Employee emp = new Employee();
        // 函數式接口Supplier是空參,返回是Integer類型的接口,
        // 而對應emp的實例方法getAge()剛剛好是空參且返回Integer類型的數據,符合上面注意事項1的要求
        Supplier<Integer> supplier = () -> emp.getAge();
        Supplier<Double> sup2 = emp::getSalary;
        System.out.println(supplier.get());
    }

    // 類::方法名
    @Test
    public void testSupplier() {
        Comparator<String> comparator = (x, y) -> x.compareTo(y);
        // 要求參數第一個值作為方法體的調用者,第二個參數值作為方法體的被調用者(參數)符合注意事項2的要求
        Comparator<String> compString = String::compareTo;
        System.out.println(comparator.compare("2", "3"));
        
        Comparator<Integer> com = Integer::compare;
        System.out.println(com.compare(1, 2));

        BiPredicate<String, String> predicate = String::equals;
        System.out.println(predicate.test("we", "eq"));
    }

構造器引用

這兒以函數式接口為例:可以將返回的參數R,使用構造器的構造方法。

// 當Employee有下面的構造時候
    public Employee(int age) {
        this.age = age;
    }

可構造以下這樣的一個函數式接口。

Function<Integer,Employee> fun = i -> new Employee(i)
System.out.println(fun.apply(13));

// 使用構造器引用簡化后:
Function<Integer,Employee> fun = Employee::new
System.out.println(fun.apply(15));

以上就是關于“java8新特性lambda表達式的語法是什么”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

合作市| 福建省| 福鼎市| 遵义市| 博爱县| 弥渡县| 乌什县| 沈丘县| 兴国县| 开化县| 崇左市| 黄大仙区| 京山县| 澄城县| 巴彦县| 崇仁县| 武鸣县| 鹤山市| 东源县| 沙洋县| 乳山市| 金坛市| 北京市| 乌恰县| 安阳市| 伊春市| 荃湾区| 昭通市| 青州市| 裕民县| 醴陵市| 靖宇县| 大理市| 大名县| 桂林市| 隆子县| 岱山县| 滨州市| 九龙县| 武威市| 长白|