java8 Lambda表達式簡介

 

       先闡述一下JSR(Java Specification Requests)規範,即Java語言的規範提案。是向JCP(Java Community Process)提出新增一個標準化技術規範的正式請求。任何人都可以提交JSR,可以向Java平臺增添新的API和服務。JSR已成爲Java界的一個重要標準。可以理解爲JSR是Java開發者以及授權者指定的標準,而Java開發者以及授權者形成一個JCP國際組織。職能是制定Java標準,即所有的規範都是有跡可循的。

  在Java8中推出的lambda表達式(參考JSR-335,地址爲https://jcp.org/en/jsr/detail?id=335),官方的描述是:擴展Java語言以支持緊湊的lambda表達式(閉包),以及相關的語言和庫功能,以使JavaSE的API能夠使用lambda有效表達。通俗的理解爲通過lambda表達式的本質是語法糖(Syntactic sugar,在計算機語言中添加的某種語法,這種語法對語言的功能沒有影響,但是更方便程序員使用。語法糖讓程序更加簡潔,有更高的可讀性),其底層還是通過編譯器自動推斷並生成匿名類來實現。可以使用更少的代碼來實現同樣的功能,使代碼簡潔的同時也使得Java支持閉包的功能。詳見list.stream()和java.util.function包下提供了諸多的function接口。

  lambda表達式的語法:

     (parameters) -> expression 或

     (parameters) -> { statements; },

    即() -> {},等同於 new Interface(){}

    2. 代碼大覽

package com.mengyao.bigdata.lambda;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Map、List和class的lambda使用
 * lambda本質是 (parameters) -> expression; 或者 (parameters) -> { statements; }。即() -> {},等同於 new Interface(){}
 * @author mengyao
 *
 */
public class Test1 {

    public static void main(String[] args) {
        // ==== 1 ==== Map的lambda示例,jdk8之前的寫法就不貼出來了
        Map<String, Integer> map = new HashMap<String, Integer>() {{
            put("spark", 1);
            put("storm", 1);
            put("hadoop", 1);
            put("flink", 1);
        }};
        /**
         * parameters確定
         *         map.forEach參數爲java.util.function.BiConsumer<? super String, ? super Integer> action,是一個接口的聲明,
         *         實現採用的是for(Map.Entry<K, V> entry : entrySet())將entry的k和v作爲參數傳遞到action.accept(k,v)中 驗證,到此k,v參數已確定。
         * expression使用
         *         接下來是給到lambda的expression來使用
         * 所以如下3個map.forEach同理
         */
        map.forEach((k,v) -> System.out.println(k+":"+v));
        map.forEach((k,v) -> {System.out.println(k+":"+v);});
        map.forEach((k,v) -> {
            if (k.equals("spark")) {
                System.out.println(k+":"+v);
            }
        });
        
        System.out.println("====");
        
        // ==== 2 ==== List的lambda示例
        List<String> list = new ArrayList<String>(10) {{
            add("spark");
            add("storm");
            add("hadoop");
            add("flink");
        }};
        // 與map.forEach同理
        list.forEach(System.out::println);//System.out是PrintStream的實例,::println即爲調用System.out對象的println方法
        list.forEach(item -> System.out.println(item));
        list.forEach(item -> {System.out.println(item);});
        list.forEach(item -> {
            if (item.equals("spark")) {
                System.out.println(item);
            }
        });
        
        //==== 3 ==== 自定義類的lambda使用
        // 接口類非lambda方式使用
        System.out.println("==== "+new MathService() {
            @Override
            public int plus(int a, int b) {
                return a+b;
            }
        }.plus(1, 2));
        
        // 接口類lambda方式使用1(實現plus方法)
        MathService service = (a,b) -> a+b;
        System.out.println("==== "+service.plus(1, 2));
        // 接口類lambda方式使用2,將接口的實現作爲參數
        print((a,b)->a+b);
        
    }

    /**
     * 使用接口作爲參數,通常方法內部會調用接口的方法
     * @param service
     */
    static void print(MathService service) {
        int a =1,b=2;
        System.out.println(service.plus(a, b));
    }
    
}

interface MathService {
    //return a+b
    int plus(int a, int b);
}

3.lambda表達式語法格式細解;
        1)無參數,無返回值的用法 :() -> System.out.println("hello lambda");

@Test
	public void test1() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("hello runnable");
			}
		};
		r.run();
		Runnable r1 = () -> System.out.println("hello lambda");
		r1.run();
	}

 2).有一個參數,無返回值的用法: (x) -> System.out.println(x); 或者 x -> System.out.println(x); 一個參數,可以省略參數的小括號

@Test
	public void test2(){
		Consumer<String> con = (x) -> System.out.println(x);
		con.accept("有一個參數,無返回值的用法(Consumer函數式接口)");
	}

3).有兩個參數,有返回值的:(x, y) -> x + y

public void test3() {
		BinaryOperator<Integer> binary = (x, y) -> x + y;
		System.out.println(binary.apply(1, 2));// 3
	}

4)上面的例子,函數體中,都是一行語句,最後一個語法,介紹下,lambda表達式中,多行語句,分別在無返回值和有返回值的抽象類中的用法

@Test
	public void test4() {
		// 無返回值lambda函數體中用法
		Runnable r1 = () -> {
			System.out.println("hello lambda1");
			System.out.println("hello lambda2");
			System.out.println("hello lambda3");
		};
		r1.run();
 
		// 有返回值lambda函數體中用法
		BinaryOperator<Integer> binary = (x, y) -> {
			int a = x * 2;
			int b = y + 2;
			return a + b;
		};
		System.out.println(binary.apply(1, 2));// 3
 
	}

可以看到,多行的,只需要用大括號{}把語句包含起來就可以了;有返回值和無返回值的,只有一個return的區別;只有一條語句的,大括號和renturn都可以不用寫;

5).lambda的類型推斷

@Test
	public void test5() {
		BinaryOperator<Integer> binary = (Integer x, Integer y) -> x + y;
		System.out.println(binary.apply(1, 2));// 3
	}

可以看到,在lambda中的參數列表,可以不用寫參數的類型,跟java7中 new ArrayList<>(); 不需要指定泛型類型,這樣的<>棱形操作符一樣,根據上下文做類型的推斷

 

lamabd表達式中,需要有函數式接口的支持;

函數式接口定義:接口中只有一個抽象方法的接口,稱爲函數式接口;

可以使用@FunctionalInterface註解修飾,對該接口做檢查;如果接口裏,有多個抽象類,使用該註解,會有語法錯誤

 

1.lambda表達式
《java8 Lambda表達式簡介》

《java8 lambda表達式,方法的引用以及構造器的引用》

2.函數式接口
《java8 函數式接口簡介》

《JAVA8 Function接口以及同類型的特化的接口》

《JAVA8 Consumer接口》

《JAVA8 Supplier接口》

《JAVA8 UnaryOperator接口》

《JAVA8 BiConsumer 接口》

3.stream接口操作

《java8 Stream接口簡介》

《 java8 Stream-創建流的幾種方式》

《JAVA8 stream接口 中間操作和終端操作》

《JAVA8 Stream接口,map操作,filter操作,flatMap操作》

《JAVA8 stream接口 distinct,sorted,peek,limit,skip》

《java8 stream接口 終端操作 forEachOrdered和forEach》

《java8 stream接口 終端操作 toArray操作》

《java8 stream接口 終端操作 min,max,findFirst,findAny操作》

《java8 stream接口終端操作 count,anyMatch,allMatch,noneMatch》

《java8 srteam接口終端操作reduce操作》

《java8 stream接口 終端操作 collect操作》

4.其他部分

《java8 Optional靜態類簡介,以及用法》

發佈了13 篇原創文章 · 獲贊 12 · 訪問量 4555
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章