Java8 Lambda 表达式
可參考博文:
http://blog.csdn.net/codejas/article/details/78810719
在學(xué)習(xí)Lambda 之前可以先了解一下java8 中關(guān)于接口的變化,以及函數(shù)式接口的定義及作用。
(一)Lambda 表達(dá)式介紹與語法格式
1.1Lambda 介紹
Lambda 是一個(gè)匿名函數(shù),我們可以把 Lambda表達(dá)式理解為是一段可以傳遞的代碼(將代碼像數(shù)據(jù)一樣進(jìn)行傳遞)。這樣做可以寫出更簡潔、更靈活的代碼。
Lambda 表達(dá)式在Java 語言中引入了一個(gè)新的語法元素和操作符。這個(gè)操作符為 “->”, 該操作符被稱為 Lambda 操作符或剪頭操作符。它將 Lambda 分為兩個(gè)部分。
左側(cè):指定了 Lambda 表達(dá)式需要的所有參數(shù)。
右側(cè):指定了 Lambda 體,即 Lambda 表達(dá)式要執(zhí)行的功能。
1.2Lambda 格式
語法格式一:無參,無返回值
Runnable runnable = () -> System.out.println("Hello Lambda!");語法格式二:Lambda 需要一個(gè)參數(shù)
Consumer<String> fun1 = (parameter) -> System.out.println(parameter);語法格式三:Lambda 只需要一個(gè)參數(shù)時(shí),參數(shù)的小括號(hào)可以省略
Consumer<String> fun2 = parameter -> System.out.println(parameter);語法格式四:Lambda 需要兩個(gè)參數(shù),并且有返回值
BinaryOperator<Long> bo3 = (Long x, Long y) ->{System.out.println("實(shí)現(xiàn)函數(shù)接口方法!");return x + y;};語法格式五:當(dāng) Lambda 體只有一條語句時(shí),return 與大括號(hào)可以省略
BinaryOperator<Long> bo2 = (x, y) -> x + y;1.3類型推斷
BinaryOperator<Long> bo1 = (x, y) ->{System.out.println("實(shí)現(xiàn)函數(shù)接口方法!");return x + y;};參考格式四,你會(huì)發(fā)現(xiàn)在傳遞參數(shù)的可以不用指定參數(shù)的類型,因?yàn)榫幾g器推可以自動(dòng)斷出參數(shù)的數(shù)據(jù)類型。Lambda 表達(dá)式中無需指定類型,程序依然可以編譯,這是因?yàn)?javac 根據(jù)程序的上下文,在后臺(tái)推斷出了參數(shù)類型。
(二)Lambda 表達(dá)式簡單應(yīng)用
2.1Runnable 無返回值應(yīng)用
Runnable 接口中只有一個(gè)抽象方法run() ,并且使用了@FunctionalInterface 注解,表明它是一個(gè)函數(shù)式接口,所以它允許使用Lambda 表達(dá)式,下面是Java8 中Runnable 接口的源碼。
@FunctionalInterface public interface Runnable {public abstract void run(); }以前我們編寫多線程程序的時(shí)候一般都是定義一個(gè)類去實(shí)現(xiàn)Runnable 接口或者寫一個(gè)Runnable 實(shí)現(xiàn)的匿名內(nèi)部類來定義任務(wù),然后啟動(dòng)它。現(xiàn)在我們了解了Lambda 表達(dá)式可以用更簡單的方式去實(shí)現(xiàn)它。
public class LambdaTest {public static void main(String[] args) {/* Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("Hello"); }};new Thread(runnable).start();*/// Lambda 方式定義實(shí)現(xiàn)Runnable runnable1 = () -> System.out.print("Hello");new Thread(runnable1).start();} }輸出
Hello
2.2Callable 有返回值應(yīng)用
Callable 接口與Runnable 接口類似,它也是只有一個(gè)抽象方法,只不過這個(gè)抽象方法是call(),具體源碼如下。所以說它也是一個(gè)函數(shù)式接口。
@FunctionalInterface public interface Callable<V> {V call() throws Exception; }Callable 接口允許我們從運(yùn)行后的線程中獲得返回值,下面我們用Lambda 表達(dá)式去實(shí)現(xiàn)一個(gè)簡單的計(jì)算:開啟一個(gè)線程去計(jì)算1-100 數(shù)字疊加的和。
public class LambdaTest {public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<Integer> callable = () -> {int num = 0;for(int i = 0 ;i <= 100 ;i++)num += i;return num;} ;FutureTask<Integer> result = new FutureTask<>(callable);new Thread(result).start();System.out.print(result.get());} }輸出
5050
2.3具體應(yīng)用
下面是一個(gè)示例:定義一個(gè)員工類:包含字段username、age、gender和salary。這里我們以三種不同的方式區(qū)實(shí)現(xiàn)下面的需求。
需求:
①查找出薪水大于等于5000 的員工信息;
②查找出年齡大于等于20 歲的員工信息。
下面是員工類
public class Employee {private String username;private int age;private char gender; private int salary;/** 省略get 與set 方法 */@Overridepublic String toString() {return "Employee{" +"username='" + username + '\'' +", age=" + age +", gender=" + gender +", salary=" + salary +'}';} }方式一:通過最簡單的方式遍歷集合,代碼復(fù)用性很差
//所有員工信息的集合,下面的兩種實(shí)現(xiàn)方式也都使用employeesList 集合List<Employee> employeesList = Arrays.asList(new Employee("小明",20,'男',5000),new Employee("小王",22,'男',4000),new Employee("小花",18,'女',5500),new Employee("小李",25,'男',6000));//通過遍歷的形式將薪水條件符合的員工信息添加到集合中,返回條件符合的集合 public List<Employee> getEmployeesBySalary(List<Employee> employees) {List<Employee> list = new ArrayList<>();for(Employee employee : employees){if(employee.getSalary() >= 5000)list.add(employee);}return list;}@Testpublic void test1(){List<Employee> list = getEmployeesBySalary(employeesList);for(Employee employee : list){System.out.println(employee);}}//通過遍歷的形式將年齡條件符合的員工信息添加到集合中,返回條件符合的集合public List<Employee> getEmployeesByAge(List<Employee> employees) {List<Employee> list = new ArrayList<>();for(Employee employee : employees){if(employee.getAge() >= 20)list.add(employee);}return list;}@Testpublic void test2(){List<Employee> list = getEmployeesByAge(employeesList);for(Employee employee : list){System.out.println(employee);}}方式二:簡單策略模式
策略接口
//定義策略接口,因?yàn)樵摻涌谥挥幸粋€(gè)抽象方法所以也是一個(gè)函數(shù)式接口public interface MyStrategy<Employee>{boolean test(Employee employee);}測試
//返回符合條件的員工集合public List<Employee> filterEmployees(List<Employee> employees , MyStrategy<Employee> strategy) {List<Employee> list = new ArrayList<>();for(Employee employee : employees) {if(strategy.test(employee)) //根據(jù)策略添加符合對(duì)應(yīng)條件的員工list.add(employee);}return list;}//為了避免復(fù)雜不定義策略類直接傳入一個(gè)MyStrategy 形式的匿名內(nèi)部類的實(shí)現(xiàn),輸出薪水條件符合的員工@Testpublic void test5(){List<Employee> list = filterEmployees(employeesList, new MyStrategy<Employee>() {@Overridepublic boolean test(Employee employee) {return employee.getSalary() >= 5000;}});for(Employee employee : list){System.out.println(employee);}}//輸出年齡條件符合的員工@Testpublic void test6(){List<Employee> list = filterEmployees(employeesList, new MyStrategy<Employee>() {@Overridepublic boolean test(Employee employee) {return employee.getAge() >= 20;}});for(Employee employee : list){System.out.println(employee);}}方式三:策略模式 + Lambda 表達(dá)式
/** 這里仍然用到了策略模式,我們不用傳入MyStrategy 的實(shí)現(xiàn)類,代碼更加簡潔了 */@Testpublic void test7(){List<Employee> list = filterEmployees(employeesList, (e) -> e.getSalary() >= 5000);for(Employee employee : list){System.out.println(employee);}}@Testpublic void test8(){List<Employee> list = filterEmployees(employeesList, (e) -> e.getAge() >= 20);for(Employee employee : list){System.out.println(employee);}}(三)總結(jié)
這篇博文主要介紹了Lambda 的相關(guān)概念、使用方式,并通過具體的簡單例子體會(huì)到了Lambda 的簡潔。希望這篇博文能夠?yàn)槌鯇W(xué)Lambda 的讀者提供幫助。
總結(jié)
以上是生活随笔為你收集整理的Java8 Lambda 表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是企业贷款 基本要求解读
- 下一篇: Java8 接口在变化