Lambda表达式

例子见Github-JavaSE-Day08

Lambda表达式介绍

Lambda表达式是JAVA8中最重要的新功能之一。使用它可以代替只有一个抽象函数的接口函数式接口)实现,告别匿名内部类,简化代码。Lambda表达式同时还提升了对集合、框架的迭代、遍历等操作。
特点

  1. 函数式编程
  2. 参数类型自动推断
  3. 代码量少比较简洁

Lambda表达式使用

(object...atgs)->{函数式接口抽象方法实现逻辑}

  1. ()参数是一个的时候,括号可以省略
  2. 当expr逻辑非常简单时,{}和return可以省略
  3. ()中可以写类型也可以不写,它可以自行进行类型推断(最好带着)

    ()->{return 100;}
    ()->100
    (int x)->{return x+1;}
    x->x+1

告别匿名内部类,简化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 按照字符串长度从小到大排序
List<String> list = Arrays.asList("java","javascript","scala","python");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
for(String s:list) {
System.out.println(s);
}
System.out.println("---------");
Collections.sort(list,(a,b)->a.length()-b.length());
list.forEach(System.out::println);
函数式接口

只有一个抽象方法的接口交叫做函数式接口
在接口前加上@FunctionalInterface注解,如果定义了两个接口会报错。e.g Runnable接口是一个函数式接口。

常用的函数式接口
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 在java中提供了一系列函数式接口,用来接收后续传入的逻辑,
* 但是对输入输出有要求。
*/
// Function:一个输入一个输出,一般输入输出类型不同
Function<String, Integer> f1 = (str) -> {return str.length();};
System.out.println(f1.apply("abcdefg"));
// UnaryOperator:一个输入一个输出,类型相同
UnaryOperator<String> uo1 = (String u) -> {return u.concat("qqq");};
System.out.println(uo1.apply("unaryOperator"));
// BiFunction:两个输入一个输出,一般输入输出类型不同
BiFunction<Integer, String, String> bf = (a, str) -> {
return a.toString()+str;};
System.out.println(bf.apply(1,"bifunction"));
// BinaryOperator:两个输入一个输出,输入输出类型相同
BinaryOperator<String> bo = (st1,st2) -> {return st1+st2;};
System.out.println(bo.apply("Binary","operator"));
// Supplier:代表一个输出
Supplier<String> s1 = ()->{return "Supplier";};
System.out.println(s1.get());

// Consumer:代表一个输入
Consumer<String> c11 = (str) -> System.out.println(str);
c11.accept("Consumer");
// BiConsumer:代表两个输入
BiConsumer<String, Integer> bc1 = (str, i) -> System.out.println(str+","+i);
bc1.accept("BiConsumer",1);

结果:
在这里插入图片描述

在main方法外定义三个函数:

1
2
3
4
5
6
7
8
9
10
11
static int get() {
return 1;
}

static String find() {
return "find";
}

static void exec() {
find();
}

对方法进行基本调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 不管是get()还是exec(),都是在run()中进行一个具体执行的。
* 只不过返回值没有进行一个处理
*/
// 如果想要打印get方法返回值
// Runnable runnable4 = () -> {
// int i = get();
// System.out.println(i);};
Runnable runnable5 = () -> get();
Runnable runnable5 = () -> exec();
// 错误,因为run()明确没有返回值
// Runnable runnable6 = () -> 100;
runnable4.run();
runnable5.run();

再加一个自定义函数式接口

1
2
3
4
@FunctionalInterface
public interface LambdaInterface {
int get();
}

对该接口方法进行调用:

1
2
3
4
5
6
7
8
LambdaInterface li1 = () -> get(); // 调用的是staitc int get()
// LambdaInterface li2 = () -> find(); // 错误,接口明确定义要返回int类型
LambdaInterface li3 = () -> 100;
// LambdaInterface li4 = () -> ""; // 错误
LambdaInterface li5 = () -> true?0:1;

// System.out.println(li1.get()); // 可以打印出1
li1.get();
方法的引用

也是Lambda表达式的一种使用方式。用来直接访问最终让方法的调用变得非常简单。

方法引用发分类
在这里插入图片描述
在这里插入图片描述

  1. 静态方法的引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void getSize(int size) {
    System.out.println(size);
    }
    public static void main(String[] args) {
    Consumer<Integer> c1 = Test2::getSize;
    c1.accept(123);
    Consumer<Integer> c2 = (size) -> Test2.getSize(size);
    c1.accept(123);
    }

    结果:
    123
    123

  2. 实例方法的引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public String put() {
    return "put..";
    }
    public static void main(String[] args) {
    System.out.println(new Test3().put());
    Supplier<String> s1 = () -> new Test3().put();
    Supplier<String> s2 = () -> {return new Test3().put();};
    Supplier<String> s3 = new Test3()::put;
    System.out.println(s1.get());
    System.out.println(s2.get());
    System.out.println(s3.get());
    // System.out是标准输出流,是个PrintStream类对象。即调用println()普通方法
    // System.out::println
    }

    结果:
    AAA
    AAA
    AAA
    AAA

  3. 对象方法的引用(用的少)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public class Test4 {
    public static void main(String[] args) {
    Consumer<Too> c1 = (Too too)->new Too().foo();
    c1.accept(new Too());
    // Consumer<Too2> c2 = (Too too) -> new Too2().foo(); // 报错
    Consumer<Too> c2 = (Too too) -> new Too2().foo();
    c2.accept(new Too());
    Consumer<Too> c3 = Too::foo;
    c3.accept(new Too());

    BiConsumer<Too2,String> bc = (too2,str)->new Too2().show(str);
    BiConsumer<Too2,String> bc2 = Too2::show;
    bc.accept(new Too2(),"abc");
    bc.accept(new Too2(),"def");
    }
    }

    class Too{
    public Integer fun(String s) {
    return 1;
    }
    public void foo() {
    System.out.println("foo");
    }
    }
    class Too2{
    public Integer fun(String s) {
    return 1;
    }
    public void foo() {
    System.out.println("foo---too2");
    }
    public void show(String str) {
    System.out.println("show---too2--"+str);
    }
    }

    结果:
    foo
    foo—too2
    foo
    show—too2–abc
    show—too2–def

  4. 构造方法的引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public static void main(String[] args) {
    Supplier<Account> s1 = ()->new Account();
    s1.get();
    Supplier<Account> s2 = Account::new;
    s2.get();

    Supplier<List> s3 = ArrayList::new;
    Supplier<Set> s4 = HashSet::new;
    Supplier<Thread> s5 = Thread::new;
    Supplier<String> s6 = String::new;
    // Supplier<Integer> s7 = Integer::new; // 错误,没有无参构造方法

    Consumer<Integer> c1 = (age) -> new Account(age);
    Consumer<Integer> c2 = Account::new;
    c1.accept(123);
    c2.accept(234);
    Function<String,Account> f1 = (str)->new Account(str);
    Function<String,Account> f2 = Account::new;
    f1.apply("abc");
    f2.apply("bcd");
    }
    }

    class Account {
    public Account(int age) {
    System.out.println("age 参数构造"+age);
    }
    public Account(String s) {
    System.out.println("s 参数构造"+s);
    }
    public Account() {
    System.out.println("调用无参构造方法");
    }
    }

    结果:
    调用无参构造方法
    调用无参构造方法
    age 参数构造123
    age 参数构造234
    s 参数构造abc
    s 参数构造bcd