Lambda表达式简介
什么是Lambda?
Lambda是JAVA 8添加的一个新的特性,Lambda就是一个匿名函数。
为什么要使用Lambda?
使用Lambda表达式可以对一个接口进行非常简洁的实现。
@FunctionalInterface
interface Comparator{
int compare(int a, int a);
}
class MyComparator implements Comparator{
public int compare(int a, int b){
return a - b;
}
}
public class Program{
public static void main(String[] args){
//1.使用接口实现类
Comparator comparator = new MyComparator();
//2.使用匿名内部类
Comparator comparator1 = new MyComparator(){
public int compare(int a, int b){
return a - b;
}
};
//3.使用Lambda表达式来实现接口
Comparator comparator2 = (a,b) -> a - b;
}
}
Lambda对接口的要求?
虽然可以使用Lambda表达式对某些接口进行简单的实现,但是并不是所有的接口都可以用Lambda表达式来实现。要求接口中定义的必须要实现的抽象方法只能是一个。
注:在JAVA 8对接口加了一个新的特性:default。
@FunctionalInterface
修饰函数式接口的。接口中的抽象方法只有一个。
Lambda基础语法
@FunctionalInterface
public interface LambdaNoneReturnNoneParameter{
void test();
}
@FunctionalInterface
public interface LambdaNoneReturnSingleParameter{
void test(int n);
}
@FunctionalInterface
public interface LambdaNoneReturnMutipleParameter{
void test(int a, int b);
}
@FunctionalInterface
public interface LambdaSingleReturnNoneParameter{
int test();
}
@FunctionalInterface
public interface LambdaSingleReturnSingleParameter{
int test(int a);
}
@FunctionalInterface
public interface LambdaSingleReturnMultipleParameter{
int test(int a, int b);
}
public class Syntax1{
public static void main(String[] args){
//1.Lambda表达式的基础语法
//Lambda是一个匿名函数
// 参数列表 方法体
// ():用来描述参数列表
// {}:用来描述方法体
// ->:Lambda运算符,读作goes to
//无参无返回
LambdaNoneReturnNoneParameter lambda1 = () -> {
System.out.println("hello world");
};
lambda1.test();
//无返回值,单个参数
LambdaNoneReturnSingleParameter lambda2 = (int a) -> {
System.out.println(a);
};
lambda2.test(10);
//无返回值,多个参数
LambdaNoneReturnMultipleParameter lambda3 = (int a, int b) -> {
System.out.println(a+b);
};
lambda3.test(10,20);
//有返回值,无参数
LambdaSingleReturnNoneParameter lambda4 = () -> {
System.out.println("lambda4")
return 100;
};
int ret = lambda4.test();
System.out.println(ret);
//有返回值,单个参数
LambdaSingleReturnSingleParameter lambda5 = (int a) -> {
return a*2;
};
int ret2 = lambda5.test(10);
System.out.println(ret2);
//有返回值,多个参数
LambdaSingleReturnMultiplrParameter lambda6 = (int a, int b) -> {
return a+b;
};
int ret3 = lambda6.test(20,30);
System.out.println(ret3);
}
}
Lambda语法精简
public class Syntax2{
public static void main(String[] args){
//语法精简
//1.参数类型
//由于在接口的抽象方法中,已经定义了参数的数量和类型,所以在Lambda表达式中,参数的类型可以省略
//注:如果需要省略类型,则每一个参数的类型都要省略。千万不要出现省略一个参数类型,不省略一个参数类型
LambdaNoneReturnMultipleParameter lambda1 = (a, b) -> {
System.out.println("hello world");
};
//2. 参数小括号
//如果参数列表中,参数的数量只有一个,此时,小括号可以省略
LambdaNoneReturnSingleParameter lambda12= a -> {
System.out.println("hello world");
};
//3. 方法打括号
//如果方法体中只有一条语句,此时打括号可以省略
LambdaNoneReturnSingleParameter lambda3 = a -> System.out.println("hello world");
}
//4.如果方法体中唯一的一条语句是一个返回语句,则在省略掉大括号的同时也必须省略掉return
LambdaSingleReturnNoneParameter lambda4 = () -> 10;
LambdaSingleReturnMultipleParameter lambda5 = (a, b) -> a + b;
}
Lambda语法进阶
public class Syntax3{
public static void main(String[] args){
//方法引用
//可以快速的将一个Lambda表达式的实现指向一个已经实现的方法
//语法:方法的隶属者::方法名
//注:
//1.参数数量和类型一定要和接口中定义的方法一致
//2.返回值的类型一定要和接口中定义的方法一致
LambdaSingleReturnSingleParameter lambda1 = a -> change(a);
//方法引用:引用了change方法的实现
LambdaSingleReturnSingleParameter lambda2 = Syntax3::change;
}
private static int change(int a){
return a*2;
}
}
public 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类的有参构造方法执行了");
}
public String to String(){
return "Person{"+
"name="+name+''\''+
", age="+age+
'}';
}
}
public class Syntax4{
public static void main(String[] args){
PersonCreater creater = () -> new Person();
//构造方法的引用
PersonCreater creater1 = Person::new;
Person a = creater1.getPerson();
PersonCreater2 creater2 = Person::new;
Person b = creater2.getPerson("xiaoming", 10);
}
}
//需求:
interface PersonCreater{
Person getPerson();
}
interface PersonCreater{
Person getPerson(String name, int age);
}
Lambda综合案例
public class Exercise1{
//集合排序
//ArrayList<>
public static void main(String[] args){
//需求:已知在一个ArrayList中有若干个Person对象,将这些Person对象按照年龄进行降序排序
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("xiaoming",10));
list.add(new Person("lilei",11));
list.add(new Person("hanmeimei",12));
list.add(new Person("lily",9));
list.add(new Person("lucy",9));
list.add(new Person("polly",3));
list.add(new Person("uncle wang",40));
//排序
list.sort((o1,o2) -> o2.age - o1.age);
System.out.println(list);
}
}
public class Exercise2{
public static void main(String[] args){
//TreeSet自带排序使用Lambda表达式来实现Comparator接口,并实例化一个TreeSet对象,使用Comparator如果返回0,则默认这两个元素相同,就会去重
// TreeSet<Person> set = new TreeSet<>((o1,o2) -> o2.age-o1.age);
TreeSet<Person> set = new TreeSet<>((o1,o2) ->
if(o1.age>=o2.age){
return -1;
}else{
return 1;
}
});
set.add(new Person("xiaoming",10));
set.add(new Person("lilei",11));
set.add(new Person("hanmeimei",12));
set.add(new Person("lily",9));
set.add(new Person("lucy",9));
set.add(new Person("polly",3));
set.add(new Person("uncle wang",40));
System.out.println(set);
}
}
public class Exercise3{
public static void main(String[] args){
//集合遍历
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
//将集合中的每一个元素都带入到方法accept中
// list.forEach(System.out::println);
//输出集合中所有的偶数
list.forEach(ele -> {
if(ele%2==0){
System.out.println(ele);
}
});
}
}
public class Exercise4{
public static void main(String[] args){
//需求:删除集合中满足条件的元素
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("xiaoming",10));
list.add(new Person("lilei",11));
list.add(new Person("hanmeimei",12));
list.add(new Person("lily",9));
list.add(new Person("lucy",9));
list.add(new Person("polly",3));
list.add(new Person("uncle wang",40));
//删除集合中年龄大于10岁的元素
/* ListIterator<Person> it = list.listIterator();
while(it.hasNext()){
Person ele = it.next();
if(ele.age>10){
it.remove;
}
}*/
//Lambda实现
//将集合中的每一个元素都带入到test方法中,如果返回值是true,则删除这个元素
list.removeIf(ele -> ele.age > 10);
System.out.println(list);
}
}
public class Exercise5{
public static void main(String[] args){
//需求:开辟一条线程,做一个数字的输出
Thread = new Thread(() ->{
for(int i=0;i<100;i++){
System.out.println(i);
}
});
t.start();
}
}
系统内置函数式接口
import java.util.function.*;
public class FunctionalInterface{
public static void main(String[] args){
//系统内置的一些函数式接口
//Predicate<T> :参数T 返回值boolean
//IntePredicate:int -> boolean
//LongPredicate:long -> boolean
//DoublePredicate:double -> boolean
//Consumer<T>:参数T 返回值void
//IntConsumer:int -> void
//LongConsumer:long -> void
//DoubleConsumer: double -> void
//Function<T,R>:参数T 返回值R
//IntFunction<R>:int -> R
//LongFunction<R>:long -> R
//DoubleFunction<R>:double ->R
//IntToLongFunction:int->long
//IntToDoubleFunction:int -> double
//LongToIntFunction: long -> int
//LongToDoubleFunction:long -> double
//DoubleToIntFucntion:double -> int
//DoubleToLongFunction:double -> long
//Supplier<T>:参数无 返回值T
//UnaryOperator<T>:参数T 返回值T
//BinaryOperator<T>:参数T,T 返回值T
//BiFunction<T,U,R>:参数T,U 返回值R
//BiPredicate<T,U>:参数T,U 返回值boolean
//BiConsumer<T,U>:参数T,U 返回值void
}
}
闭包问题
public class ClosureDemo{
public static void main(String[] args){
int n = getNumber().get(); //可以拿到返回值
System.out.println(n);
}
private static Supplier<Integer> getNumber(){
int num = 10;
return () ->{ //引用了getNumber()里面的局部变量num,用这个方法把num这个变量包围起来,这就是闭包
return num;
};
}
}
//方法中的局部变量在这个方法执行之后就应该被销毁,但闭包会提升保卫变量的生命周期,num在getNumber()执行结束之后不会销毁,因为num在其他地方多了一个引用,所以不会销毁,这样就可以获取到某一个方法中的局部变量
public class ClosureDemo2{
public static void main(String[] args){
int a = 10;
Consumer<Integer> c = ele -> {
System.out.println(a); //变成a+1可以运行,变成a++会报错,就算在大括号下面写a++也会报错
};
c.accept(a);
}
}
//Lambda表达式中如果想要引用某一个局部变量,首先要保证它必须是一个常量,虽然没有对a进行final修饰,但是在编译的时候还是会自动加上,所以a此时就是一个常量