这里写目录标题
- lambda简述
- 以前的实现
- 初次使用lambda表达式
- Lambda表达式的语法
- 测试方法
- lambda表达式简写示范
- 测试方法
- 运行结果
- 方法引用
- 测试方法
- 运行结果
- 构造方法引用
- 定义一个Boy类
- 编写测试方法
- 运行结果
- 实际应用
- 测试代码
- 运行结果
- 内置函数式接口
- @FunctionalInterface注解
- @FunctionalInterface注解简介
- @FunctionalInterface注解特点
lambda简述
可以把Lambda表达式理解为一段可以传递的代码,可以写出更简洁、更灵活的代码。Lambda表达式是JAVA8中提供的一种新的特性,是一个匿名函数方法。
以前的实现
匿名内部类,调用执行,实际上核心的功能只有一行语句System.out.println(i+j);代码比较庞大
public class test01 {
public static void main(String[] args) {
A a=new A() {
@Override
public void add(int i, int j) {
System.out.println(i+j);
}
};
a.add(10,15);
}
}
interface A{
void add(int i,int j);
}
初次使用lambda表达式
public class test02 {
public static void main(String[] args) {
A a=(int i,int j)->{
System.out.println(i+j);
};
a.add(10,15);
}
}
interface A{
void add(int i,int j);
}
Lambda表达式的语法
Lambda表达式如果要想使用,应该是函数式接口。函数式接口首先必须是一个接口,接口里面只能有一个抽象方法(允许有默认方法、静态方法等);这种类型的接口也称为SAM接口,即Single Abstract Method Interface。
Lambda表达式语法:
(int a,int b) ->{return a+b;};
这个本质是一个函数;
Lambda表达式函数的话,只有参数列表,和方法体;
( 参数列表 ) -> { 方法体 }
( ) :参数列表;
{ } :方法体;
-> :Lambda运算符,可叫做箭头符号
一般的函数是定义是
int add(int ii,int j){
return i+j;
}
有返回值,方法名,参数列表,方法体
Lambda表达式的语法示例
下面定义了几种不同的接口,并书写了他们的lambda表达式
无参数无返回值,单个参数无返回值,两个参数无返回值,无参数有返回值:int, 单个参数有返回值:int,多个参数有返回值:int
测试方法
public class test03{
public static void main(String[] args) {
// 无参数无返回值
A a=()->{
System.out.println("无参数无返回值");
};
a.test();
// 单个参数无返回值
B b=(int i)->{
System.out.println("单个参数无返回值 i="+i);
};
b.test(3);
// 两个参数无返回值
C c=(int i,int j)->{
System.out.println("两个参数无返回值 i+j="+(i+j));
};
c.test(10,15);
// 无参数有返回值:int
D d=()->{
System.out.print("无参数有返回值 ");
return 100;
};
System.out.println(d.test());
// 单个参数有返回值:int
E e=(int i)->{
System.out.print("单个参数有返回值i= ");
return i;
};
System.out.println(e.test(520));
// 多个参数有返回值:int
F f=(int i,int j)->{
System.out.print("多个参数有返回值i-j=");
return i-j;
};
System.out.println(f.test(10,80));
}
}
interface A{
// 无参数无返回值
void test();
}
interface B{
//单个参数无返回值
void test(int i);
}
interface C{
// 两个参数无返回值
void test(int i,int j);
}
interface D{
// 无参数有返回值
int test();
}
interface E{
//单个参数有返回值
int test(int i);
}
interface F{
//多个参数有返回值
int test(int i,int j);
}
lambda表达式简写示范
lambda 表达式形式为 ()->{},-> 左边是形参列表, -> 右边是实现体。
lambda 方法如果没有参数或有两个及以上的参数,则 小括号不能省略。
lambda 方法可以省略参数的类型,可以通过上下文进行推断。
lambda 方法如果只有一个参数,则小括号可以省略。
lambda 方法体如果只有一行语句,则 大括号和return都可省略。
省略了大括号,则必须省略 return,省略了 return ,则必须省略 {},这俩要么成对出现,要么都不出现
测试方法
public class test04{
public static void main(String[] args) {
/** 1,参数类型可以省略
2,假如只有一个参数,()括号可以省略
3,如果方法体只有一条语句,{}大括号可以省略
4,如果方法体中唯一的语句是return返回语句,那省略大括号的同事return也要省略
*/
// 无参数无返回值
//省略了花括号
A a=()-> System.out.println("无参数无返回值");
a.test();
// 单个参数无返回值
//省略了花括号和小括号和参数类型
B b=i-> System.out.println("单个参数无返回值 i="+i);
b.test(3);
// 两个参数无返回值
//省略了花括号和参数类型
C c=(i,j)-> System.out.println("两个参数无返回值 i+j="+(i+j));
c.test(10,15);
// 无参数有返回值:int
//省略了花括号和参数类型
D d=()->{
System.out.print("无参数有返回值 ");
return 100;
};
System.out.println(d.test());
// 单个参数有返回值:int
// E e=(int i)->{
// System.out.print("单个参数有返回值i= ");
// return i;
// };
//为示范方法体只有一个return语句
// 先把sout语句删除掉只保留一个return语句
//只有一个参数先省略了参数类型和小括号,只有一条语句省略花括号和return关键字
E e=i->i;
System.out.println("单个参数有返回值i="+e.test(520));
// 多个参数有返回值:int
F f=( i,j)->{
System.out.print("多个参数有返回值i-j=");
return i-j;
};
System.out.println(f.test(10,80));
}
}
interface A{
// 无参数无返回值
void test();
}
interface B{
//单个参数无返回值
void test(int i);
}
interface C{
// 两个参数无返回值
void test(int i,int j);
}
interface D{
// 无参数有返回值
int test();
}
interface E{
//单个参数有返回值
int test(int i);
}
interface F{
//多个参数有返回值
int test(int i,int j);
}
运行结果
方法引用
有时候多个lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护;
这时候可以用方法引用实现
语法:
static方法 类名::方法名
普通方法 对象名::方法名
测试方法
public class test05 {
public static void main(String[] args) {
test05 t5=new test05();
// 普通方法 对象名::方法名
F f1=t5::test01;
System.out.println("普通方法 对象名::方法名 "+f1.test(10,80));
// static方法 类名::方法名
F f2 = test05::test02;
System.out.println("static方法 类名::方法名 "+f2.test(10, 80));
}
public int test01(int i,int j){
return i+j;
}
public static int test02(int i,int j){
return i-j;
}
}
interface F {
//多个参数有返回值
int test(int i, int j);
}
运行结果
构造方法引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,
那么就可以使用构造方法引用;
语法:类名::new
定义一个Boy类
public class Boy {
private String name;
private int age;
private String hobby;
public Boy(){
System.out.println("这是Boy类的无参构造方法");
}
public Boy(String name,int age,String hobby){
System.out.println("这是Boy类的有参构造方法");
this.name=name;
this.age=age;
this.hobby=hobby;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Boy{" +
"name='" + name + '\'' +
", age=" + age +
", hobby='" + hobby + '\'' +
'}';
}
}
编写测试方法
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
public class test06 {
public static void main(String[] args) {
//一般写法
// A a=()->{
// return new Boy();
// };
// System.out.println(a.getBoy());
//
// B b=(String name,int age,String hobby)->{
// return new Boy( name, age,hobby);
// };
// System.out.println(b.getBoy("cxk", 888,"篮球"));
//构造方法引用写法
A a=Boy::new;
System.out.println(a.getBoy());
B b=Boy::new;
System.out.println(b.getBoy("cxk", 888,"篮球"));
}
}
interface A{
Boy getBoy();
}
interface B{
Boy getBoy(String name,int age,String hobby);
}
运行结果
实际应用
我们可以通过lambda表达式来排序集合中的元素,在sort方法中有一个接口Comparator接口,Comparator接口有个compare抽象方法传入两个参数,返回一个整型数字,我们可以通过该方法实现对集合的排序。
sort方法里有一个Comparator接口
Comparator接口有个compare方法,我们可以通过该方法实现对集合的排序
我们还可以通过lambda表达式来遍历集合,forEach方法中有消费者Consumer接口,接口里有个接口参数的accept的方法,传入值而不返回任何参数。
再看下集合的forEach方法,点进去:
有个消费者Consumer接口,再点进去:
接口里有个接口参数的accept的方法;
所以我们直接方法引用 直接输出每次的遍历值即可;
System.out::println
测试代码
import java.util.ArrayList;
import java.util.List;
public class test07 {
public static void main(String[] args) {
List<Boy> list=new ArrayList<>();
list.add(new Boy("张三",10,"乒乓球"));
list.add(new Boy("王二",41,"篮球"));
list.add(new Boy("李四",31,"网球"));
list.add(new Boy("麻子",21,"吃饭"));
list.add(new Boy("无名氏",25,"上网"));
// 排序
System.out.println("集合排序lambda方式");
list.sort((o1,o2)->o1.getAge()-o2.getAge());
System.out.println(list);
//遍历集合
System.out.println("遍历集合lambda方式(一般情况)");
list.forEach(e-> System.out.println(e));
// 遍历集合
//方法引用由::双冒号操作符标示
System.out.println("遍历集合lambda方式(方法引用)");
list.forEach(System.out::println);
}
}
运行结果
内置函数式接口
在java8中使用Lambda表达式时候,java已经内置了四大核心函数式接口,
分别是:1.消费型接口2.供给型接口3.函数型接口4.断言型接口
因此一些常用/简单的接口,用户可以不用自定义了,直接用系统提供的函数接口即可。
@FunctionalInterface注解
@FunctionalInterface注解简介
可以看到Consumer接口,Comparator接口都有@FunctionalInterface注解
Java8为函数式接口引入了一个新的注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口的定义时,编译器会报错。
这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces
@FunctionalInterface注解特点
接口有且仅有一个抽象方法
允许定义静态方法
允许定义默认方法
允许java.lang.Object中的public方法
该注解不是必须的,如果一个接口符合"函数式接口"定义,不加该注解是没有影响的。