Loading

Java8 Lambda表达式

Lambda表达式简介

  1. Lambda表达式是Java 8的新特性,是一个函数式接口。
  2. 使用Lamda表达式可以对一个接口进行十分简单的实现。

Lambda对接口的要求:

Lambda要求接口中定义的必须实现的抽象方法只能是一个。

@FunctionInterface

用来修饰函数式接口,接口中的抽象方法只能有一个。

Lambda基础语法

因为Lambda 是一个匿名函数,所以只需要关注返回值类型、参数列表和方法体,不需要关注方法名,并且在Lambda中返回值类型不需要显式的表示出来。

():用来描述参数列表

{}:用来描述方法体

->:Lambda运算符,读作:goes to

自定义函数式接口

无参无返回值

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    void add();
}


class test {
    public static void main(String[] args) {
        Math math = () -> {
            System.out.println("无参无返回...");
        };
        math.add();
    }
}

无参有一个参数

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    void add(int a);
}


class test {
    public static void main(String[] args) {
        Math math = (a) -> {
            System.out.println("无返回值,有一个参数..." + a);
        };
        math.add(666);
    }
}

无参有多个参数

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    void add(int a, int b, int c);
}


class test {
    public static void main(String[] args) {
        Math math = (a, b, c) -> {
            System.out.println("无返回值,有多个参数..." + (a + b + c));
        };
        math.add(1, 2, 3);
    }
}

有返回值,无参数

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    int add();
}


class test {
    public static void main(String[] args) {
        Math math = () -> {
            return 0;
        };
        int result = math.add();
        System.err.println(result);
    }
}

有返回值,有一个参数

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    int add(int a);
}


class test {
    public static void main(String[] args) {
        Math math = (a) -> {
            return a;
        };
        int result = math.add(1);
        System.err.println(result);
    }
}

有返回值,有多个参数

/**
 * @author leizige
 */
@FunctionalInterface
public interface Math {

    int add(int a, int b);
}


class test {
    public static void main(String[] args) {
        Math math = (int a, int b) -> {
            return a + b;
        };
        int result = math.add(1, 2);
        System.err.println(result);
    }
}

Lambda表达式语法精简

  1. 参数

    由于再接口的抽象方法中,已经定义了参数的数量和类型,所以在Lambda中参数的类型可以省略。

    注意:如果需要省参数类型,则每一个参数的类型都要省略;

  2. 参数小括号

    如果参数列表中,参数的数量只有一个,此时小括号可以省略。

  3. 方法大括号

    如果方法体中只有一条语句,大括号可以省略。

  4. return

    如果方法体中唯一的一条语句是一个返回语句,则在省略掉大括号的同时,需要把return去掉。

省略参数类型

    Math math = (a,b)->{
        System.out.println();
    };

省略参数小括号

    Math math = a -> {
            System.out.println(a);
    };

省略方法大括号

    Math math = a -> System.out.println(a);

省略 return 语句

	Math math = () ->  10;

Lambda表达式方法引用

方法引用:

  1. 可以快速的将一个Lambda表达式的实现指向一个已经实现的方法。
  2. 语法:方法的隶属者::方法名

注意:

  1. 参数的数量和类型一定要和接口中定义的方法一致。
  2. 返回值的类型一定要和接口中定义的方法一致。
@Data
@ToString
/* 为Student类生成无参和有参构造*/
@NoArgsConstructor
@AllArgsConstructor
class Student {
    private String name;
    private Integer age;
}

@FunctionalInterface
interface StudentOne {
    Student getStudent();
}

@FunctionalInterface
interface StudentTwo {
    Student getStudent(String name, Integer age);
}


class test {
    public static void main(String[] args) {
        StudentOne s1 = Student::new;

        //无参构造方法引用
        StudentOne s2 = Student::new;
        Student result1 = s2.getStudent();
        System.err.println(result1);

        //有参构造方法引用
        StudentTwo p3 = Student::new;
        Student result2 = p3.getStudent("zs", 23);
        System.err.println(result2);
    }
}

内置函数接口使用

核心内置函数接口介绍

函数式接口 参数类型 返回类型 函数式接口 用途
Consumer T void void accept(T t); 对T类型参数操作,无返回结果。
supplier T T get(); 返回T类型参数。
Function T R R apply(T t); 对类型T参数操作,返回R类型参数。
Predicate T boolean boolean test(T t); 断言型接口,对类型T进行条件筛选。

四大核心函数式接口

Consumer 消费型接口

void accept(T t);

import java.math.BigDecimal;
import java.util.function.Consumer;
import java.util.function.IntConsumer;

/**
 * @author leizige
 */
public class ConsumerTest {
    public static void main(String[] args) {

        /* Consumer<T> 消费型接口 */
        shopping1(BigDecimal.valueOf(1000), money -> System.err.println("消费金额¥" + money));
        shopping2(2000, money -> System.err.println("消费金额¥" + money));

    }

    public static void shopping1(BigDecimal money, Consumer<BigDecimal> consumer) {
        consumer.accept(money);
    }

    public static void shopping2(int money, IntConsumer consumer) {
        consumer.accept(money);
    }
}

除了上面使用的 Consumer 和 IntConsumer 之外,还可以使用 LongConsumer、DoubleConsumer 等,使用方法和上面一样。

Supplier 供给型接口

T get();

import lombok.ToString;

import java.util.Random;
import java.util.function.Supplier;

/**
 * @author leizige
 */
public class SupplierTest {
    public static void main(String[] args) {
        /* Supplier<T> 供给型接口 */
        Integer random = random(() -> new Random().nextInt());
        System.err.println("random :" + random);

        Person person = (Person) create(Person::new);
        System.err.println("person : " + person);
    }

    public static <T> T random(Supplier<T> supplier) {
        return supplier.get();
    }

    public static Object create(Supplier<?> supplier) {
        return supplier.get();
    }
}

@ToString
class Person {
    private String name;
    private String age;
}

除了上面使用的 Supplier 接口,还可以使用 IntSupplier 、DoubleSupplier 、LongSupplier 、BooleanSupplier等,使用方法和上面一样。

Function<T, R> 函数式接口

R apply(T t);

/**
 * @author leizige
 */
public class FunctionTest {
    public static void main(String[] args) {

        String newStr = convert("oldStr", (oldStr) -> oldStr.toUpperCase());
        System.err.println(newStr);

        Integer length = length("HelloWorld", String::length);
        System.err.println("HelloWorld length : " + length);
    }

    /**
     * function的作用是转换,将一个值转为另外一个值
     *
     * @param oldStr   oldStr
     * @param function Function
     * @return newStr
     */
    public static String convert(String oldStr, Function<String, String> function) {
        return function.apply(oldStr);
    }

    /**
     * 泛型的第一个参数是转换前的类型,第二个是转化后的类型
     */
    public static Integer length(String str, Function<String, Integer> function) {
        return function.apply(str);
    }
}

Predicate 函数式接口

boolean test(T t);

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @author leizige
 */
public class PredicateTest {
    public static void main(String[] args) {
        Predicate<Integer> result1 = num -> num < 10;
        System.err.println(result1.test(9));

        compareString();
        compareObject();
        filterNumber();
    }

    /**
     * 比较字符串
     */
    public static void compareString() {
        String a = "666";
        String b = "666";
        Predicate<String> result = v -> v.equals(b);
        System.err.println(result.test(a));
    }

    /**
     * 比较对象
     */
    public static void compareObject() {
        Student stu1 = new Student();
        Student stu2 = new Student("zs", 23);
        Predicate<Student> result1 = v -> v == stu2;
        System.out.println(result1.test(stu1));

        Student stu3 = stu2;
        Predicate<Student> result2 = v -> v == stu2;
        System.out.println(result2.test(stu3));
    }

    /**
     * 过滤
     */
    public static void filterNumber() {
        Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
        Predicate<Integer> predicate = num -> num >= 6;
        numbers.filter(predicate).forEach(System.err::print);
    }
}

@NoArgsConstructor
@AllArgsConstructor
class Student {
    private String name;
    private Integer age;
}
If you’re going to reuse code, you need to understand that code!
posted @ 2020-12-05 21:15  不颓废青年  阅读(112)  评论(0编辑  收藏  举报