参考:https://www.bilibili.com/video/BV164411E7Ny
Lambda是JAVA 8添加的新特性,说白了,Lambda是一个匿名函数
使用Lambda表达式可以对一个接口的方法进行非常简洁的实现
接口的抽象方法只能是一个,lambda表达式才能实现该接口
在JAVA8中 ,对接口加了一个新特性:default
可以使用default对接口方法进行修饰,被修饰的方法在接口中可以默认实现
修饰函数式接口的,接口中的抽象方法只有一个
lambda表达式是实现一种接口的方式
()里面传入的是实现方法的参数列表
// 1.Lambda表达式的基础语法
// Lambda是一个匿名函数 一般关注的是以下两个重点
// 参数列表 方法体
/**
* ():用来描述参数列表
* {}:用来描述方法体 有时可以省略
* ->: Lambda运算符 读作goes to
* 例 Test t=()->{System.out.println("hello word")}; 大括号可省略
*/
public class Syntax {
public static void main(String[] args) {
}
}
//无返回值无参数
@FunctionalInterface
interface LambdaNoneReturnNoneParameter {
void test();
}
//无返回值单个参数
@FunctionalInterface
interface LambdaNoneReturnSingleParameter{
void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface LambdaNoneReturnMulParameter{
void test(int a, int b);
}
//有返回值单个参数
@FunctionalInterface
interface LambdaSingleReturnSingleParameter{
int test(int a);
}
//有返回值多个参数
@FunctionalInterface
interface LambdaSingleReturnMulParameter{
int test(int a, int b);
}
System.out.println("<-----test01----->");
// 无返回值无个参数 LambdaNoneReturnNoneParameter
LambdaNoneReturnNoneParameter lambda01=()->{
System.out.println("test01");
};
lambda01.test();
System.out.println("<-----test02----->");
// 无返回值单个参数 LambdaNoneReturnSingleParameter
LambdaNoneReturnSingleParameter lambda02 = (a) -> {
System.out.println("test02"+"---"+a);
};
lambda02.test(123);
System.out.println("<-----test03----->");
// 无返回值多个参数 LambdaNoneReturnMulParameter
LambdaNoneReturnMulParameter lambda03 = (a, b) -> {
System.out.println("test03" + "-----" + (a + b));
};
lambda03.test(3,4 );
System.out.println("<-----test04----->");
// 有返回值单个参数 LambdaSingleReturnSingleParmter
LambdaSingleReturnSingleParameter lambda04 = (a) -> {
System.out.println("test04" + "---" + a);
return a;
};
System.out.println(lambda04.test(5));
System.out.println("<-----test05----->");
// 有返回值多个参数 LambdaSingleReturnMulParameter
LambdaSingleReturnMulParameter lambda05=(a,b)->{
System.out.println("test05"+"---"+a+b);
return a+b;
};
System.out.println(lambda05.test(3,4 ));
}
/**
* 语法精简
* 1.参数类型
* 由于在接口的抽象方法中,已经定义了参数的数量类型 所以在Lambda表达式中参数的类型可以省略
* 备注:如果需要省略类型,则每一个参数的类型都要省略,千万不要一个省略一个不省略
*/
LambdaNoneReturnMutipleParmeter lambda1=(int a,int b)-> {
System.out.println("hello world");
};
可以精简为:
LambdaNoneReturnMutipleParmeter lambda1=(a,b)-> {
System.out.println("hello world");
};
参数的数量只有一个,可以省略()
/**
* 2.参数小括号
* 如果参数列表中,参数的数量只有一个 此时小括号可以省略
*/
LambdaNoneReturnSingleParmeter lambda2=(a)->{
System.out.println("hello world");
};
可以精简为:
LambdaNoneReturnSingleParmeter lambda2= a->{
System.out.println("hello world");
};
方法体中只有一条语句,可以省略{}
/**
* 3.方法大括号
* 如果方法体中只有一条语句,此时大括号可以省略
*/
LambdaNoneReturnSingleParmeter lambda3=a->{
System.out.println("hello world");
};
可以精简为:
LambdaNoneReturnSingleParmeter lambda3=a->System.out.println("hello world");
方法体中唯一的一条语句是一个返回语句,可以省略return
/**
* 4.如果方法体中唯一的一条语句是一个返回语句
* 贼省略大括号的同时 也必须省略return
*/
LambdaSingleReturnNoneParmeter lambda4=()->{
return 10;
};
可以精简为:
LambdaSingleReturnNoneParmeter lambda4=()->10;
LambdaSingleReturnNoneParmeter lambda4=(a,b)->{
return a+b;
};
可以精简为:
LambdaSingleReturnMutipleParmeter lambda5=(a,b)->a+b;
在实际应用过程中,一个接口在很多地方都会调用同一个实现,例如:
LambdaSingleReturnMutipleParmeter lambda1=(a,b)->a+b;
LambdaSingleReturnMutipleParmeter lambda2=(a,b)->a+b;
这样一来每次都要写上具体的实现方法 a+b,如果需求变更,则每一处实现都需要更改,基于这种情况,可以将后续的是实现更改为已定义的方法,需要时直接调用就行
/**
*方法引用:
* 可以快速的将一个Lambda表达式的实现指向一个已经实现的方法
* 方法的隶属者 如果是静态方法 隶属的就是一个类 其他的话就是隶属对象
* 语法:方法的隶属者::方法名
* 注意:
* 1.引用的方法中,参数数量和类型一定要和接口中定义的方法一致
* 2.返回值的类型也一定要和接口中的方法一致
*/
public class Syntax {
public static void main(String[] args) {
LambdaSingleReturnSingleParameter lambda1=a->a*2;
LambdaSingleReturnSingleParameter lambda2=a->a*2;
LambdaSingleReturnSingleParameter lambda3=a->a*2;
//简化
LambdaSingleReturnSingleParameter lambda4=a->staticMethod(a);
//方法引用
LambdaSingleReturnSingleParameter lambda5=Syntax::staticMethod;
}
public static int staticMethod(int a){
return a*2;
}
}
需求
两个接口,各有一个方法,一个接口的方法需要引用Person的无参构造,一个接口的方法需要引用Person的有参构造 用于返回两个Person对象,例:
package lambda;
public class Syntax1 {
public static void main(String[] args) {
}
}
class Person {
public String name;
public int age;
public Person() {
System.out.println("Person的无参构造方法执行");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person的有参构造方法执行");
}
}
interface PersonCreater01{
//通过Person的无参构造实现
Person getPerson();
}
interface PersonCreater02{
//通过Person的有参构造实现
Person getPerson(String name,int age);
}
PersonCreater01 creater=()->new Person();
//引用的是Person的无参构造
//PersonCreater接口的方法指向的是Person的方法
PersonCreater01 creater1=Person::new; //等价于上面的()->new Person()
//实际调用的是Person的无参构造 相当于把接口里的getPerson()重写成new Person()。
Person a=creater1.getPerson();
//引用的是Person的有参构造
PersonCreater02 creater2=Person::new;
Person b=creater2.getPerson("张三",18);
需求:已知在一个ArrayList中有若干各Person对象,将这些Person对象按照年龄进行降序排列
//需求:已知在一个ArrayList中有若干各Person对象,将这些Person对象按照年龄进行降序排列
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("张三",10));
list.add(new Person("李四",12));
list.add(new Person("王五",13));
list.add(new Person("赵六",14));
list.add(new Person("李雷",11));
list.add(new Person("韩梅梅",8));
list.add(new Person("jack",10));
System.out.println("排序前:"+list);
//将排列的依据传入 具体的方法指向的是 内部元素的age相减 sort会依据结果的正负进行降序排列
//sort 使用提供的 Comparator对此列表进行排序以比较元素。
list.sort((o1, o2) -> o2.age-o1.age);
System.out.println("排序后:"+list);
treeset 自带排序 要添加进集合,必须实现Comparator接口
/**Treeset 自带排序
* 但是现在不知道Person谁大谁小无法排序
* 解决方法:
* 使用Lambda表达式实现Comparator接口,并实例化一个TreeSet对象
* 注意:在TreeSet中如果Comparator返回值是 0 会判断这是两个元素是相同的 会进行去重
* TreeSet set=new TreeSet<>((o1, o2) -> o2.age-o1.age);
* 这个获取的对象打印会少一个Person
* 此时我们将方法修改
*/
TreeSet<Person> set=new TreeSet<>((o1, o2) ->{
if(o1.age>=o2.age){
return -1;
}else {
return 1;
}
});
set.add(new Person("张三",10));
set.add(new Person("李四",12));
set.add(new Person("王五",13));
set.add(new Person("赵六",14));
set.add(new Person("李雷",11));
set.add(new Person("韩梅梅",8));
set.add(new Person("jack",10));
System.out.println(set);
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6,7,8,9);
/**
* list.forEach(Consumer super E> action)
* api文档解释: 对 集合中的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常。
* 将集合中的每一个元素都带入到接口Consumer的方法accept中 然后方法accept指向我们的引用
* 输出集合中的所有元素
* list.forEach(System.out::println);
*/
//输出集合中所有的偶数
list.forEach(ele->{
if(ele%2==0){
System.out.println(ele);
}
});
ArrayList<Person> list=new ArrayList<>();
list.add(new Person("张三",10));
list.add(new Person("李四",12));
list.add(new Person("王五",13));
list.add(new Person("赵六",14));
list.add(new Person("李雷",11));
list.add(new Person("韩梅梅",8));
list.add(new Person("jack",10));
//删除集合中年龄大于12的元素
/**
* 之前迭代器的做法
* ListIterator it = list.listIterator();
* while (it.hasNext()){
* Person ele=it.next();
* if(ele.age>12){
* it.remove();
* }
* }
*/
/**
* lambda实现
* 逻辑
* 将集合中的每一个元素都带入到接口Predicate的test方法中,
* 如果返回值是true,则删除这个元素
*/
list.removeIf(ele->ele.age>10);
System.out.println(list);
需求:开辟一条线程 做一个数字的输出
/**
* 通过Runnable 来实例化线程
*/
Thread t=new Thread(()->{
for(int i=0;i<100;i++){
System.out.println(i);
}
});
t.start();
// Predicate : 参数是T 返回值boolean
// 在后续如果一个接口需要指定类型的参数,返回boolean时可以指向 Predicate
// IntPredicate int -> boolean
// LongPredicate long -> boolean
// DoublePredicate double -> boolean
// Consumer : 参数是T 无返回值(void)
// IntConsumer int ->void
// LongConsumer long ->void
// DoubleConsumer double ->void
// Function : 参数类型T 返回值R
// IntFunction int -> R
// LongFunction long -> R
// DoubleFunction double -> R
// IntToLongFunction int -> long
// IntToDoubleFunction int -> double
// LongToIntFunction long -> int
// LongToDoubleFunction long -> double
// DoubleToLongFunction double -> long
// DoubleToIntFunction double -> int
// Supplier : 参数 无 返回值T
// UnaryOperator :参数T 返回值 T
// BiFunction : 参数 T、U 返回值 R
// BinaryOperator :参数 T、T 返回值 T
// BiPredicate : 参数T、U 返回值 boolean
// BiConsumer : 参数T、U 无返回值
/**
* 常用的 函数式接口
* Predicate、Consumer、Function、Supplier
*/
ackage com.alan.closure;
import java.util.function.Supplier;
public class ClosureDemo {
public static void main(String[] args) {
/**
* lambda的闭包会提升包围变量的生命周期
* 所以局部变量 num在getNumber()方法内被 get()引用 不会在getNumber()方法执行后销毁
* 这种方法可以在外部获取到某一个方法的局部变量
*/
int n=getNumber().get();
System.out.println(n);
}
private static Supplier<Integer> getNumber(){
int num=10;
/**
* Supplier supplier=()->num;
* return supplier;
*/
return ()->{
return num;
};
}
}
*************************************************************************
import java.util.function.Consumer;
public class ClosureDemo2 {
public static void main(String[] args) {
int a=10;
Consumer<Integer> c=ele->{
System.out.println(a+1);
//System.out.println(ele);
//System.out.println(a++); 会报错
//在lambda中引用局部变量 这个变量必须是一个常量
};
//a++; 这样也会导致内部报错
//如果在内部已经引用局部变量 参数传递后 打印的还是 10
c.accept(1);
}
}