lambda表达式
1.背景介绍
- lambda是java8的新特性---->匿名函数
- lambda用于接口的简洁实现(接口的实现有三种方式)
- lambda要求接口中只有一个抽象方法(java8引入的default修饰除外)
- 函数式接口:接口中只有一个抽象方法(可使用@FunctionalInterface对接口进行编译检查)
1.1 接口的三种实现方式
package com.zhanglei.interfaceImplementsMethods;
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//1.实现类实现接口
Comparator c1=new MyComparator();
int r1=c1.comparator(1,2);
System.out.println("first:"+r1);
//2.匿名内部类实现接口
Comparator c2=new Comparator() {
@Override
public int comparator(int a,int b) {
return a-b;
}
};
int r2=c2.comparator(1, 3);
System.out.println("second:"+r2);
//3.lambda表达式实现接口
Comparator c3=(a,b)->a-b;
int r3=c3.comparator(1, 4);
System.out.println("third:"+r3);
}
}
@FunctionalInterface
interface Comparator{
int comparator(int a,int b);
}
class MyComparator implements Comparator{
public int comparator(int a,int b) {
return a-b;
}
}
输出:
first:-1
second:-2
third:-3
2. lambda实现接口
2.1 准备多个接口
示例:
package interfaces;
public interface LambdaNoneReturnMultiParam {
void test(int a, int b);
}
package interfaces;
public interface LambdaSingleReturnNoParam {
int test();
}
2.2 传统的lambda实现接口
package syntax;
import interfaces.LambdaNoneReturnMultiParam;
import interfaces.LambdaNoneReturnNoParam;
import interfaces.LambdaNoneReturnSingleParam;
import interfaces.LambdaSingleReturnMultiParam;
import interfaces.LambdaSingleReturnNoParam;
import interfaces.LambdaSingleReturnSingleParam;
public class Syntax1 {
public static void main(String[] args) {
//1.lambda基础语法
//lambda为匿名函数
//函数组成:返回值类型,方法名,参数列表,方法体
//匿名函数组成:参数列表,方法体
// ():参数列表
// {}:方法体
// ->:lambda运算符,读作goes to
//2.lambda测试
//2.1 无参无返回
LambdaNoneReturnNoParam l1=()->{
System.out.println("我是无参无返回");
};
l1.test();
//2.2 单参无返回
LambdaNoneReturnSingleParam l2=(int a)->{
System.out.println("我是单参无返回"+a);
};
l2.test(11);
//2.3 多参无返回
LambdaNoneReturnMultiParam l3=(int a,int b)->{
System.out.println("我是多参无返回"+a+" "+b);
};
l3.test(11, 22);
//2.4 无参有返回
LambdaSingleReturnNoParam l4=()->{
return 111;
};
int r1=l4.test();
System.out.println("我是无参有返回"+r1);
//2.5 单参有返回
LambdaSingleReturnSingleParam l5=(int a)->{
return a;
};
int r2=l5.test(222);
System.out.println("我是单参有返回"+r2);
//2.6 多参有返回
LambdaSingleReturnMultiParam l6=(int a,int b)->{
return a+b;
};
int r3=l6.test(111,222);
System.out.println("我是多参有返回"+r3);
}
}
输出:
我是无参无返回
我是单参无返回11
我是多参无返回11 22
我是无参有返回111
我是单参有返回222
我是多参有返回333
- 注意看注释部分
- 传统的lambda写法还是很多代码
2.3 精简的lambda写法
package syntax;
import interfaces.LambdaNoneReturnMultiParam;
import interfaces.LambdaNoneReturnNoParam;
import interfaces.LambdaNoneReturnSingleParam;
import interfaces.LambdaSingleReturnMultiParam;
public class Syntax2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//语法精简
//1.参数类型
//由于接口中定义了参数的类型和数量,所以lambda中可以省略其类型(要省略就全部省略不能部分省略)
LambdaNoneReturnMultiParam l1=(a,b)->{
System.out.println("参数类型省略");
};
l1.test(1, 1);
//2.参数小括号
//如果参数只有一个,则小括号可以省略
LambdaNoneReturnSingleParam l2=a->{
System.out.println("参数小括号省略");
};
l2.test(1);
//3.方法体大括号
// 如果方法体中只有一条语句,则大括号可以省略,分为有return和无return
// 无return,直接省略大括号
LambdaNoneReturnNoParam l3=()->System.out.println("方法大括号省略");
l3.test();
// 有return,直接省略return和大括号
LambdaSingleReturnMultiParam l4=(a,b)->a-b;
int r1=l4.test(1, 2);
System.out.println("方法大括号省略之return"+r1);
}
}
输出:
参数类型省略
参数小括号省略
方法大括号省略
方法大括号省略之return-1
2.4 进阶的方法引用
package syntax;
import interfaces.LambdaSingleReturnSingleParam;
public class Syntax3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//方法引用:
//将lambda表达式的实现指向一个已经实现的方法(当方法需要多次调用和修改时)
//格式:方法的隶属者::方法名
LambdaSingleReturnSingleParam l0=a-> a*2;
LambdaSingleReturnSingleParam l1=a-> change(a);
System.out.println(l1.test(1));
// 静态方法对应 类名::方法名
LambdaSingleReturnSingleParam l2=Syntax3::change;
System.out.println(l2.test(3));
Syntax3 s3=new Syntax3();
// 实例方法对应 对象::方法名
LambdaSingleReturnSingleParam l3=s3::change3;
System.out.println(l3.test(5));
}
public static int change(int a) {
return a*2;
}
public int change3(int a) {
return a*3;
}
}
输出:
2
6
15
2.5 进阶的构造方法引用
package data;
public class Person {
private String name;
private int age;
public Person() {
System.out.println("无参构造被调用!");
}
public Person(String name,int age) {
this.name=name;
this.age=age;
System.out.println("有参构造被调用!");
}
}
package syntax;
import data.Person;
public class Syntax4 {
public static void main(String[] args) {
// TODO Auto-generated method stub
PersonCreator1 pc1=()->{
return new Person();
};
PersonCreator1 pc2=()->new Person();
//构造方法的引用
PersonCreator1 pc3=Person::new;
Person a=pc3.getPerson();
PersonCreator2 pc4=Person::new;
Person b=pc4.getPerson("zhanglei", 25);
}
}
//函数式接口,保证只有一个抽象方法!!!
interface PersonCreator1{
Person getPerson();
// Person getPerson(String name,int age);
}
interface PersonCreator2{
// Person getPerson();
Person getPerson(String name,int age);
}
输出:
无参构造被调用!
有参构造被调用!
3.lambda实战
3.1 集合排序
package data;
public class Person {
public String name;
public int age;
public Person() {
System.out.println("无参构造被调用!");
}
public Person(String name,int age) {
this.name=name;
this.age=age;
System.out.println("有参构造被调用!");
}
public String toString(String name,int age) {
return "Person的name为:"+name+",年龄为:"+age;
}
public String toString() {
return "Person的name为:"+name+",年龄为:"+age;
}
}
- toString无参才是重写,有参是普通方法
package Exercise;
import java.util.ArrayList;
import data.Person;
public class Exercise1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Person> a1=new ArrayList<>();
a1.add(new Person("zhangsan",21));
a1.add(new Person("lisi",22));
a1.add(new Person("wangwu",23));
a1.add(new Person("zhaoliu",19));
a1.add(new Person("zhangniu",24));
a1.add(new Person("zhangwei",25));
//排序1
a1.sort((o1,o2)->o1.age-o2.age);
System.out.println(a1);
//排序1
a1.sort((o1,o2)->o2.age-o1.age);
System.out.println(a1);
}
}
输出:
有参构造被调用!
有参构造被调用!
有参构造被调用!
有参构造被调用!
有参构造被调用!
有参构造被调用!
[Person的name为:zhaoliu,年龄为:19, Person的name为:zhangsan,年龄为:21, Person的name为:lisi,年龄为:22, Person的name为:wangwu,年龄为:23, Person的name为:zhangniu,年龄为:24, Person的name为:zhangwei,年龄为:25]
[Person的name为:zhangwei,年龄为:25, Person的name为:zhangniu,年龄为:24, Person的name为:wangwu,年龄为:23, Person的name为:lisi,年龄为:22, Person的name为:zhangsan,年龄为:21, Person的name为:zhaoliu,年龄为:19]
- public void sort(Comparator<? super E> c) 参数为Comparator接口
- 该接口是函数式接口(其中的equals方法不是抽象方法!)
- 如此就可以使用lambda表达式
- lambda表达式来实现int compare(T o1,T o2)
- 当其返回值小于0,等于0,大于0分别对应o1小于o2,o1等于o2,o1大于大于o2
- 因此可以利用返回值来进行升序和降序的选择
- 思考为什么o1.age-o2.age和o2.age-o1.age可以对应升序和降序
- 考察源码和算法能力了
3.2 集合遍历(for each)
package exercise;
import java.util.ArrayList;
import java.util.Collections;
public class Exercise2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> a1=new ArrayList<>();
Collections.addAll(a1,1,2,3,4,5,6,7,8,9,10);
//方法引用实现Consumer函数式接口中的accept方法
a1.forEach(System.out::println);
System.out.println("******");
//输出集合中所有的偶数
a1.forEach(ele->{
if(ele%2==0) {
System.out.println(ele);
}
});
}
}
输出:
1
2
3
4
5
6
7
8
9
10
******
2
4
6
8
10
3.3 线程实例化
package exercise;
public class Exercise3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread th=new Thread(()->{
for(int i=0;i<10;i++) {
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
th.start();
}
}
输出:
0
1
2
3
4
5
6
7
8
9
解释:
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
- Runnable接口是函数式接口,所以可以用lambda表达式实例化线程对象