1. 程式人生 > 實用技巧 >Java8 新特性-Lambda表示式

Java8 新特性-Lambda表示式

目錄

1、Lambda表示式介紹

package com.zjw;

/**
 * Lambda表示式介紹
 * Java 8的一個大亮點是引入Lambda表示式,使用它設計的程式碼會更加簡潔,通過Lambda表示式,可以替代我們以前經常寫的匿名內部類來實現介面。
 * Lambda表示式的本質是一個匿名函式。
 */
public class Lambda01
{
    public static void main(String[] args) {

        //1、通過子類建立物件
        F1 f = new F1Class();

        //2、使用匿名內部類
        F1 f2 = new F1() {
            @Override
            public int add(int a, int b) {
                return a+b;
            }
        };

        //3、使用Lambda表示式建立
        /**
         * Lambda語法
         * Lambda只有引數列表和方法體
         * (引數列表)->{方法體}
         */
        F1 f1 = (int a , int b)->{
            return a+b;
        };
        System.out.println(f1.add(1,2));

    }

}

interface F1{
    int add(int a , int b);
}

class F1Class implements F1{

    @Override
    public int add(int a, int b) {
        return a+b;
    }
}

2、Lambda表示式語法細講

使用Lambda實現不同的介面

package com.zjw;

/**
 *Lambda表示式語法細講
 * 我們搞一個案例,介面方法引數,無參,單個引數,兩個引數,有返回值,沒有返回值
 */
public class Lambda02
{
    public static void main(String[] args) {

        //無返回值 無參
        F1 f1 = ()->{
            System.out.println("f1");
        };
        f1.test();

        //無返回值 單參
        F2 f2 = (int a)->{
            System.out.println("f2="+a);
        };
        f2.test(2);

        //無返回值 多參
        F3 f3 = (int a , int b)->{
            System.out.println("f3="+(a+b));
        };
        f3.test(1,2);

        //有返回值 無參
        F4 f4 = () -> {
            return 4;
        };
        System.out.println(f4.test());

        //有返回值 單引數
        F5 f5 = (int a)->{
            return a;
        };
        System.out.println(f5.test(5));

        //有返回值 多參
        F6 f6 = (int c , int d)->{
            return c-d;
        };
        System.out.println(f6.test(7,1));


    }

    interface F1{
        void test();
    }

    interface F2{
        void test(int a);
    }

    interface F3{
        void test(int a , int b);
    }

    interface F4{
        int test();
    }

    interface F5{
        int test(int a);
    }

    interface F6{
        int test(int a , int b);
    }

}
f1
f2=2
f3=3
4
5
6

3、 Lambda表示式語法精簡

package com.zjw;

/**
 * Lambda語法精簡
 * 1、引數型別可以省略
 * 2、假如只有一個引數,()括號可以省略
 * 3、如果方法體只有一條語句,{}大括號可以省略
 * 4、如果方法體中唯一的語句是return語句,那省略大括號的同時return也要省略
 */
public class Lambda03
{
    public static void main(String[] args) {

        F1 f1 = ()->System.out.println("f1");
        f1.test();

        F2 f2 = a->System.out.println("f2="+a);
        f2.test(2);

        F3 f3 = (a , b)->System.out.println("f3="+(a+b));
        f3.test(1,2);

        F4 f4 = () -> 4;
        System.out.println(f4.test());

        F5 f5 = a-> a;
        System.out.println(f5.test(5));

        F6 f6 = (c , d)->c-d;
        System.out.println(f6.test(7,1));

    }

    interface F1{
        void test();
    }

    interface F2{
        void test(int a);
    }

    interface F3{
        void test(int a , int b);
    }

    interface F4{
        int test();
    }

    interface F5{
        int test(int a);
    }

    interface F6{
        int test(int a , int b);
    }

}

4、 Lambda方法引用

引用靜態方法、普通方法

package com.zjw;

/**
 * 有時候多個lambda表示式實現函式是一樣的話,我們可以封裝成通用方法,以便於維護;
 * 這時候可以用方法引用實現:
 * 語法: 物件::方法
 * 假如是static方法,可以直接 類名::方法
 */
public class Lambda04
{
    public static void main(String[] args) {

        Lambda04 lambda04 = new Lambda04();
        F1 f1 = (a,b)-> testB(a,b);
//        F1 f1 = lambda04::testA;
        System.out.println(f1.test(1,2));
        F1 f2 = lambda04::testA;
        System.out.println(f2.test(2,3));

        F1 f3 = Lambda04::testB;
        System.out.println(f3.test(3,1));

    }

    public int testA(int a , int b){
        return a+b;
    }

    public static int testB(int a , int b){
        return a-b;
    }


    interface F1{
        int test(int a , int b);
    }

}

引用構造方法

package com.zjw;

public class Dog {
    private String name;
    private int age ;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
/**
 * 如果函式式介面的實現恰好可以通過呼叫一個類的構造方法實現,那麼就可以使用構造方法引用;
 * 語法: 類名::new
 */
public class Lambda05
{
    public static void main(String[] args) {

        DogService dogService = Dog::new;
        Dog dog = dogService.getDog();
        System.out.println(dog);

        DogService2 dogService2 = Dog::new;
        Dog dog2 = dogService2.getDog("狗狗", 2);
        System.out.println(dog2);


    }

    interface DogService{
        Dog getDog();
    }

    interface DogService2{
        Dog getDog(String name , int age );
    }

}

5、 綜合例項

package com.zjw;

import java.util.ArrayList;
import java.util.List;

/**
 * 綜合例項
 */
public class Lambda06
{
    public static void main(String[] args) {

        List<Dog> list = new ArrayList<>();
        list.add(new Dog("aa",1));
        list.add(new Dog("aa",5));
        list.add(new Dog("aa",3));
        list.add(new Dog("aa",4));
        list.add(new Dog("aa",2));

        //lambda 排序
        list.sort((dog1,dog2)->dog2.getAge()-dog1.getAge());
        System.out.println(list);

        //lambda 遍歷
        list.forEach(System.out::println);

        //刪除年齡大於3的
        list.removeIf(dog -> dog.getAge()>3);
        list.forEach(System.out::println);

    }
}

6、 @FunctionalInterface註解

package com.zjw;

/**
 * @FunctionalInterface註解
 *
 * 前面我們會發現Consumer介面,Comparator介面都有@FunctionalInterface註解
 *
 * 這個註解是函式式介面註解,所謂的函式式介面,當然首先是一個介面,然後就是在這個接口裡面只能有一個抽象方法。
 * 這種型別的介面也稱為SAM介面,即Single Abstract Method interfaces
 *
 * 特點
 * - 介面有且僅有一個抽象方法
 * - 允許定義靜態方法
 * - 執行定義預設 方法
 * - 允許java.lang.Object中的public方法
 * - 該註解不是必須的,如果一個介面符合"函式式介面"定義,那麼加不加該註解都沒有影響。加上該註解能夠更好地讓編譯器進行檢查。如果編寫的不是函式式介面,但是加上了@FunctionalInterface,那麼編譯器會報錯
 */
public class Lambda07
{
    public static void main(String[] args) {

    }

    @FunctionalInterface
    interface TestInterface{

        //抽象方法
        public void sub();

        //java.lang.Object中的public方法
        public boolean equals(Object var);

        //預設方法
        default void defaultMethod(){}

        //靜態方法
        public static void staticMethod(){}
    }

}

7、內建函式式介面

Java.util.function,提供四個核心介面
1、功能型介面(Function)

public interface Function<T,R>{public R apply(T t)}

【接收一個引數,返回一個處理結果】

2、消費型介面(Consumer)

public interface Consumer<T>{public void accept(T t)}

【只接收資料,不返回結果】

3、供給型介面(Supplier)

public interface Supplier<T>{public T get()}

【不接收資料,可以返回結果】

4、斷言型介面(Predicate)

public interface Predicate<T>{public boolean test(T t)}

【進行判斷操作使用】

函式式介面——接收引數並且返回一個處理結果
String類有一個方法:

public  boolean startsWith(String str)
package com.test;
import java.util.function.Function;
public class Test03 {
	public static void main(String[] args) {
		Function<String, Boolean> fun = "##123"::startsWith;
		System.out.println(fun.apply("#"));
	}
}

消費型介面(Consumer)

package com.test;
import java.util.function.Consumer;
class MyDemo
{
	public void print(String str)
	{
		System.out.println(str);
	}
}
public class Test03 {
	public static void main(String[] args) {
		Consumer<String> fun = System.out::println;
		fun.accept("Hello World!");;
	}
}

供給型介面

package com.test;
import java.util.function.Supplier;
public class Test03 {
	public static void main(String[] args) {
		Supplier<String> fun = "hello"::toUpperCase;
		System.out.println(fun.get());
	}
}