JDK1.8新特性--Lambda表達式

 非原創(chuàng),知識總結(jié)性文章

1、Lambda表達式的介紹

函數(shù)式編程思想概述

在數(shù)學中,函數(shù)就是有輸入量、輸出量的一套計算方案,也就是“拿什么東西做什么事情”。相對而言,面向?qū)ο筮^分強調(diào)“必須通過對象的形式來做事情”,而函數(shù)式思想則盡量忽略面向?qū)ο蟮膹碗s語法——強調(diào)做什么,而不是以什么形式做。

傳統(tǒng)寫法代碼示例

public class demo01 {
    public static void main(String[] args) {
        Runnable runnable = new Runnable(){
            public void run(){
                System.out.println("多線程任務(wù)執(zhí)行");
            }
        };
        new Thread(runnable).start();
    }
}

說明:

  • Thread類需要Runnable接口作為參數(shù),其中的抽象run方法是用來指定線程任務(wù)內(nèi)容的核心;
  • 為了指定run的方法體,不得不需要Runnable接口的實現(xiàn)類;
  • 為了省去定義一個RunnableImpl實現(xiàn)類的麻煩,不得不使用匿名內(nèi)部類;
  • 必須覆蓋重寫抽象run方法,所以方法名稱、方法參數(shù)、方法返回值不得不再寫一遍,且不能寫錯;
  • 而實際上,似乎只有方法體才是關(guān)鍵所在

上述示例使用Lambda的寫法

public class demo01 {
    public static void main(String[] args) {
        new Thread(()->{
            System.out.println("多線程啟動");
        }).start();
    }
}

上例中,核心代碼其實只是如下所示的內(nèi)容:() -> System.out.println("多線程任務(wù)執(zhí)行!")

Lambda標準格式

Lambda省去面向?qū)ο蟮臈l條框框,格式由3個部分組成:
  • 一些參數(shù);
  • 一個箭頭;
  • 一段代碼。
    Lambda表達式的標準格式為:(參數(shù)類型 參數(shù)名稱) -> { 代碼語句 }
    格式說明:
  • 小括號內(nèi)的語法與傳統(tǒng)方法參數(shù)列表一致:無參數(shù)則留空;多個參數(shù)則用逗號分隔;
  • ->是新引入的語法格式,代表指向動作;
  • 大括號內(nèi)的語法與傳統(tǒng)方法體要求基本一致。

練習:使用Lambda標準格式(無參無返回)

給定一個廚子Cooker接口,內(nèi)含唯一的抽象方法makeFood,且無參數(shù)、無返回值。如下:
public interface Cooker {
    void makeFood();
}

在下面的代碼中,請使用Lambda的標準格式調(diào)用invokeCook方法,打印輸出“吃飯啦!”字樣:

public class demo01 {
    public static void main(String[] args) {
        invokeCook(() -> {
            System.out.println("吃飯啦!");
        });

    }
    private static void invokeCook(Cooker c){
        c.makeFood();
    }
}

Lambda的參數(shù)和返回值

需求:使用Lambda表達式對存在數(shù)組中的Person類型的對象數(shù)據(jù)按照年齡的降序輸出。

傳統(tǒng)寫法:

public class Demo02 {
    public static void main(String[] args) {
        // 本來年齡亂序的對象數(shù)組
        Person[] array = {
            new Person("古力娜扎", 19),
            new Person("迪麗熱巴", 18),
            new Person("馬爾扎哈", 20) };

        // 匿名內(nèi)部類
        Comparator<Person> comp = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        };
        Arrays.sort(array, comp); // 第二個參數(shù)為排序規(guī)則,即Comparator接口實例

        for (Person person : array) {
            System.out.println(person);
        }
    }
}

Lambda寫法:

public class demo02 {
    public static void main(String[] args) {
        // 本來年齡亂序的對象數(shù)組
        Person[] array = {
                new Person("古力娜扎", 19),
                new Person("迪麗熱巴", 18),
                new Person("馬爾扎哈", 20) };

        Arrays.sort(array,(Person p1,Person p2) -> {
            return p2.getAge() - p1.getAge();
        });

        for (Person person : array) {
            System.out.println(person);
        }
    }
}

Lambda省略格式

  Lambda強調(diào)的是“做什么”而不是“怎么做”,所以凡是可以根據(jù)上下文推導得知的信息,都可以省略。例如上例還可以使用Lambda的省略寫法:
public static void main(String[] args) {
    invokeCalc(120, 130, (a, b) -> a + b);
}

省略規(guī)則:
在Lambda標準格式的基礎(chǔ)上,使用省略寫法的規(guī)則為:

  • 小括號內(nèi)參數(shù)的類型可以省略;
  • 如果小括號內(nèi)有且僅有一個參數(shù),則小括號可以省略;
  • 如果大括號內(nèi)有且僅有一個語句,則無論是否有返回值,都可以省略大括號、return關(guān)鍵字及語句分號。
    注意:關(guān)于第三點如果省略一個,那么必須同時都得省略。

2、Lambda表達式的應(yīng)用

Lambda表達式的使用條件是
  • 使用lambda表達式的類型必須是一個只含有一個抽象方法的借口
  • lambda只能使用final修飾的變量

forEach遍歷Map

//1.forEach遍歷Map
System.out.println("\n1.forEach遍歷Map");
Map<String, Object> map = new HashMap<>();
map.put("key1", 11);
map.put("key2", 12);
map.put("key3", 13);
map.put("key4", 14);
map.forEach((key,value)->{
    System.out.println("key:"+key+",value:"+value);
});

輸出:
1.forEach遍歷Map
key:key1,value:11
key:key2,value:12
key:key3,value:13
key:key4,value:14

forEach遍歷List

//2.forEach遍歷List
System.out.println("\n2.forEach遍歷List");
List<Integer> list =  new ArrayList<Integer>() ;
list.add(1);
list.add(2);
list.add(3);
list.forEach(value->System.out.println(value));

輸出:
2.forEach遍歷List
1
2
3

在多線程中使用Lambda表達式

//3.在多線程中使用Lambda表達式
System.out.println("\n3.在多線程中使用Lambda表達式");
new Thread(()->System.out.println("new Thread start")).start();

輸出:
3.在多線程中使用Lambda表達式
new Thread start

自定義Lambda表達式功能

//4.自定義Lambda表達式功能
interface MathOperator{
    int operator(int a, int b);
    
}
public static void calc(int a ,int b, MathOperator operator){
    System.out.println(operator.operator(a, b));
}

System.out.println("\n4.自定義Lambda表達式功能");
MathOperator add = (a,b)->a+b ;
MathOperator sub = (a,b)->a-b ;
MathOperator mul = (a,b)->a*b ;
MathOperator div = (a,b)->a/b ;

calc(3, 5, add);
calc(3, 5, sub);
calc(3, 5, mul);
calc(3, 5, div);

輸出:
4.自定義Lambda表達式功能
8
-2
15
0

Predicate接口實現(xiàn)數(shù)據(jù)過濾

System.out.println("\n5.Predicate接口實現(xiàn)數(shù)據(jù)過濾");
List<String> filterList = new LinkedList<>() ;
filterList.add("1");
filterList.add("abc");
filterList.add("java");
filterList.add("python2");
filterList.add("python3");
filterList.add("c++");
filture(filterList, str->str.startsWith("j")) ;
//單條件過濾
filterList.stream().filter(str->str.contains("++")).forEach(value->System.out.println(value)) ;
//多條件邏輯過濾
Predicate<String> startWith = str->str.startsWith("p") ;
filterList.stream().filter(startWith.and(str->str.contains("2"))).forEach(value->System.out.println(value)) ;

輸出:
5.Predicate接口實現(xiàn)數(shù)據(jù)過濾
java
c++
python2

Lambda的map和reduce操作

/3.在多線程中使用Lambda表達式
System.out.println("\n6.Lambda的map和reduce操作");
List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
//map操作讓每一個元素加上它之前的0.12倍
costBeforeTax.stream().map(cost -> cost+0.12*cost).forEach(System.out::println);
System.out.println(costBeforeTax.stream().reduce((sum,cost)->sum+cost).get()); //求和

輸出:
6.Lambda的map和reduce操作
112.0
224.0
336.0
448.0
560.0
1500

創(chuàng)建一個字符串列表,每個字符串長度大于2

System.out.println("\n7.創(chuàng)建一個字符串列表,每個字符串長度大于2");
List<String> strList = Arrays.asList(new String[]{"abc","de","abcde"});
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);

輸出:
7.創(chuàng)建一個字符串列表,每個字符串長度大于2
Original List : [abc, de, abcde], filtered list : [abc, abcde]

獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值

System.out.println("\n8.獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值");
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());

輸出:
8.獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值
Highest prime number in List : 29
Lowest prime number in List : 2
Sum of all prime numbers : 129
Average of all prime numbers : 12.9

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容