Lambda表达式
Lambda表达式
1. Lambda表达式介绍
Lambda 表达式是Java 8引入的重要新特性。Java8中Lambda表达式简化了匿名内部类的形式,并且可以达到同样的效果,使用它设计的代码会更加简洁。通过Lambda表达式,可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数。
2. Lambda表达式的使用
interface Cal{
int add(int a,int b);
}
public class Program {
public static void main(String[] args) {
Cal c1=new Cal() {
@Override
public int add(int a, int b) {
return a+b;
}
};
int c=c1.add(1,2);
System.out.println(c);
}
}
这个是我们以前的实现,匿名内部类,然后调用执行;
用Lambda表达式改写下:
interface Cal{
int add(int a,int b);
}
public class test1 {
public static void main(String[] args) {
Cal c1=(int a,int b)->{return a+b;};
int c=c1.add(1, 2);
System.out.println(c);
}
}
匿名内部类,直接改成了:
Cal c1=(int a,int b) ->{return a+b;};
3.Lambda表达式语法
(int a,int b) ->{return a+b;};
这个本质是一个函数;
一般的函数类似如下:
int add(int a,int b){
return a+b;
}
有返回值,方法名,参数列表,方法体
Lambda表达式函数的话,只有参数列表,和方法体;
( 参数列表 ) -> { 方法体 }
说明:
( ) :用来描述参数列表;
{ } : 用来描述方法体;
-> :Lambda运算符,可以叫做箭头符号,或者goes to
总共6种情况,接口方法无返回值和有返回值分2种,其中无参数、单个参数和多个参数又分3种情况。
package javaMIANXIANGDUIXIANG;
interface If1{
/* 无参数无返回值 */
void test();
}
interface If2{
/* 单个参数无返回值
* @param a
* */
void test(int a);
}
interface If3{
/* 两个参数无返回值
* @param a,b
* */
void test(int a,int b);
}
interface If4{
/* 无参数无返回值 */
int test();
}
interface If5{
/* 单个参数有返回值 */
int test(int a);
}
interface If6{
/* 两个参数有返回值 */
int test(int a,int b);
}
public class test2 {
public static void main(String[] args) {
If1 if1 = ()->{
System.out.println("无参数无返回值");
};
if1.test();
If2 if2 = (int a)->{
System.out.println("单个参数无返回值 a="+a);
};
if2.test(3);
If3 if3 = (int a,int b)->{
System.out.println("两个参数无返回值 c="+a+b);
};
if3.test(3, 4);
If4 if4 = ()->{
System.out.println("无参数有返回值");
return 100;
};
System.out.println(if4.test());
If5 if5 = (int a)->{
System.out.println("单个参数有返回值");
return a;
};
System.out.println(if5.test(300));
If6 if6 = (int a,int b)->{
System.out.println("两个参数有返回值");
return a+b;
};
System.out.println(if6.test(30, 50));
}
}
4. Lambda表达式精简语法
1,参数类型可以省略
2,假如只有一个参数,()括号可以省略
package javaMIANXIANGDUIXIANG;
interface If7{
int test(int a);
}
public class test1 {
public static void main(String[] args) {
If7 if7=a->{return a;};
System.out.println(if7.test(3));
}
}
3,如果方法体只有一条语句,{}大括号可以省略
package javaMIANXIANGDUIXIANG;
interface If7{
void test(int a);
}
public class test1 {
public static void main(String[] args) {
If7 if7=a->System.out.println("a="+a);
if7.test(3);
}
}
4,如果方法体中唯一的语句是return返回语句,那省略大括号的同事return也要省略
package javaMIANXIANGDUIXIANG;
interface If7{
int test(int a);
}
public class test1 {
public static void main(String[] args) {
If7 if7=a->a;
System.out.println(if7.test(3));
}
}
5. 方法引用
适用于多个lambda表达式实现函数是一样的情况,可以封装成通用方法,以便于维护。
语法:
对象::方法
如果是static方法,直接类名::方法
interface If8{
int program(int a);
}
public class test3 {
public static void main(String[] args) {
test3 t=new test3();
If8 if8=t::program;
If8 if81=test3::program1;//讲方法都封装到If8接口中
System.out.println(if8.program(2));
System.out.println(if81.program(3));
}
public int program(int a) {
return a;
}
public static int program1(int a) {
return a*a;
}
}
6. 构造方法的引用
如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,
那么就可以使用构造方法引用;
语法:类名::new
class Person{
private String name;
private int Age;
public Person() {
System.out.println("无参构造方法");
}
public Person(String name,int age) {
System.out.println("有参构造方法");
this.name=name;
this.Age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public int getAge(int age) {
return age;
}
public void setAge(int age) {
this.Age=age;
}
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + Age +
'}';
}
}
interface PersonService{
Person getPerson();
}
interface PersonService2{
Person getPerson(String name,int age);
}
public class test4 {
public static void main(String[] args) {
//普通调用构造方法
PersonService personService=()->new Person();
personService.getPerson();
PersonService2 personService2=(String name,int age)->new Person("BOb",18);
System.out.println(personService2.getPerson(null,0));//由实际创建Person类对象时传入参数,这里的参数没有实际意义
System.out.println();
//调用类的构造方法实现
//引用无参构造方法
PersonService personService3=Person::new;
personService3.getPerson();
//引用有参构造方法
PersonService2 dogService21=Person::new;
System.out.println(dogService21.getPerson("Alice",19));
}
}
PersonService和PersonService2两个接口分别调用了Person类的构造方法。
在主函数先通过普通调用方法,直接利用lambda表达式创建对象的方式调用了Person类中的构造方法,进行了无参和有参构造方法在接口中的实现。
通过 类名::new 的方式直接进行构造方法的引用,有参构造方法在引用后进行传参实现成员变量的赋值操作。
7. 综合案例
import java.util.List;
import java.util.ArrayList;
class Person1{
private String name;
private int Age;
public Person1(String name,int age) {
this.name=name;
this.Age=age;
}
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;
}
public String toString() {
return "Person1{" +
"name='" + name + '\'' +
", age=" + Age +
'}';
}
}
public class test5 {
public static void main(String[] args) {
List<Person1>list=new ArrayList();
list.add(new Person1("BoB",15));
list.add(new Person1("Alice",16));
list.add(new Person1("Smith",16));
list.add(new Person1("Kitty",8));
list.add(new Person1("Jerry",25));
list.add(new Person1("Tom",75));
list.add(new Person1("Maxima",45));
// 排序
System.out.println("Lambda集合排序:");
list.sort((o1,o2)->o1.getAge()-o2.getAge());//Lambda表达式重写sort方法Comparator接口中的compareTo方法,由小到大排序
System.out.println(list);
// 遍历集合
System.out.println("Lambda集合遍历:");
list.forEach(System.out::println);
}
}
查看sort方法中的Comparator接口
查询Comparetor接口中的compare方法
查看一下集合的forEach方法:
Consumer接口中有2个方法,有且只有一个声明为accept(T t)的方法,接收一个输入参数并且没有返回值。
8. @Functionallnterface注解
在Consumer接口,Comparator接口都有@Functionallnterface注解。
该注解是函数式接口注解,函数式接口,首先是一个接口,在这个接口中只能有一个抽象方法。
这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
● 接口有且仅有一个抽象方法
● 允许定义静态方法
● 允许定义默认方法
●允许java.lang.Object中的public方法
● 该注解不是必须的,如果一个接口符合“函数式接口”定义,加不加该备注都没有影响。加上该注解能够更好的让编译器进行检查。如果编写的不是函数式接口,但是加上了@Functionallnterface,编译器会报错。
// 正确的函数式接口
@FunctionalInterface
public interface TestInterface {
// 抽象方法
public void sub();
// java.lang.Object中的public方法
public boolean equals(Object var1);
// 默认方法
public default void defaultMethod(){
}
// 静态方法
public static void staticMethod(){
}
}
// 错误的函数式接口(有多个抽象方法)
@FunctionalInterface
public interface TestInterface2 {
void add();
void sub();
}