lambda表达式

1.什么是lambda表达式

Lambda是JAVA8添加的一个新的特性。说白了,Lambda就是一个匿名函数。

2.为什么要使用lambda表达式

使用Lambda表达式可以对一个接口进行非常简洁的实现。

3.lambda对接口的要求

虽然可以使用Lambda表达式对某些接口进行简单的实现,但是并不是所有的接口都可以用Lambda表达式来实现。要求接口中定义的必须要实现的抽象方法只能是一个。

@FunctionalInterface
修饰函数式接口的。接口中的抽象方法只有一个。

//这个注解是用来限制下面这个接口只能有一个抽象方法
@FunctionalInterface
interface Comparator{
	int compare(int a,int b);
}

class MyComparator implements Comparator{

	@Override
	public int compare(int a, int b) {
		// TODO Auto-generated method stub
		return a-b;
	}
	
}

public class Test1 {
	public static void main(String[] args) {
		//1 .使用接口实现类
		Comparator comparator1=new MyComparator();
		
		//2.使用匿名内部类实现
		Comparator comparator2=new Comparator() {
			
			@Override
			public int compare(int a, int b) {
				// TODO Auto-generated method stub
				return a-b;
			}
		};
		
		//3.使用lambda表达式实现接口
		Comparator comparator3=(a,b)->a-b;
	}
}

4.lambda基础语法

//无返回值,无参数
@FunctionalInterface
public interface LambdaNoneReturnNoneParameter {
	void test();
}
//无返回值,单个参数
@FunctionalInterface
public interface LambdaNoneReturnSingleParameter {
	void test(int n);
}
//无返回值,多个参数
@FunctionalInterface
public interface LambdaNoneReturnMutipleParameter {
	void test(int m,int n);
}
//单个返回值,无参数
@FunctionalInterface
public interface LambdaSingleReturnNoneParameter {
	int test();
}

//单个返回值,单个参数
@FunctionalInterface
public interface LambdaSingleReturnSingleParameter {
	int test(int n);
}
//单个返回值,多个参数
@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();//hello world
		
		//无返回值,单个参数
		LambdaNoneReturnSingleParameter lambda2=(int a)->{
			System.out.println(a);
		};
		lambda2.test(10);//10
		
		//无返回值,多个参数
		LambdaNoneReturnMutipleParameter lambda3=(int a,int b)->{
			System.out.println(a+" "+b);
		};
		lambda3.test(2, 3);//2 3
		
		//有返回值,无参数
		LambdaSingleReturnNoneParameter lambda4=()->{
			return 1;
		};
		System.out.println(lambda4.test());//1
		
		//有返回值,一个参数
		LambdaSingleReturnSingleParameter lambda5=(int a)->{
			return a;
		};
		System.out.println(lambda5.test(5));//5
		
		//有返回值,多个参数
		LambdaSingleReturnMultipleParameter lambda6=(int a,int b)->{
			return a+b;
		};
		System.out.println(lambda6.test(2, 3));//5
	}
}

5.lambda表达式语法精简

public class Syntax2 {
	public static void main(String[] args) {
		//语法精简
		//1.参数
		//由于在接口的抽象方法中,已经定义了参数的数量和类型,所以在lambda表达式中,参数的类型可以忽略
		//备注:如果需要省略参数类型,则每一个参数类型都要省略
		LambdaNoneReturnMutipleParameter lambda1=(a,b)->{
			System.out.println(a+b);
		};
		lambda1.test(2,3);//5
		
		//2.参数小括号
		//如果参数列表中,参数的数量只有一个,此时小括号可以省略
		LambdaNoneReturnSingleParameter lambda2=a->{
			System.out.println(a);
		};
		lambda2.test(3);//3
		
		//3.方法大括号
		//如果方法体重只有一条语句,那么大括号可以省略
		LambdaNoneReturnSingleParameter lambda3=a->System.out.println(a);
		lambda3.test(4);//4
		
		//4.如果方法体中唯一一条语句是一个返回语句,则在省略大括号的同时,也必须省略return
		LambdaSingleReturnNoneParameter lambda4=()->10;
		System.out.println(lambda4.test());//10
		
		LambdaSingleReturnMultipleParameter lambda5=(a,b)->a+b;
		System.out.println(lambda5.test(2, 3));//5
		
	}
}

6.lambda语法进阶

普通方法引用

public class Syntax3 {
	public static int change(int a){
		return a*2;
	}
	public static void main(String[] args) {
		//方法引用:
		//可以快速的将一个lambda表达式的实现指向一个已经实现的方法
		//语法:方法的隶属者::方法名
		
		//注意:
		//1.参数数量和类型一定要和接口中定义的方法一致
		//2.返回值的类型一定要和接口中定义的类型一致
		LambdaSingleReturnSingleParameter lambda1=a->change(a);
		System.out.println(lambda1.test(1));//2
		
		//方法引用:引用了change方法实现
		LambdaSingleReturnSingleParameter lambda2=Syntax3::change;
		System.out.println(lambda2.test(3));//6
		

	}
}

构造方法引用

public class Person {
	public String name;
	public int age;

	public Person() {
		super();
		System.out.println("无参方法执行了");
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		System.out.println("有参方法执行了");
	}

}
//需求:
interface PersonCreate{
	Person getPerson();
}
interface PersonCreate2{
	Person getPerson(String name,int age);
}
public class Syntax4 {
	public static void main(String[] args) {
		PersonCreate create1=()->{
			return new Person();
		};
		//可以再次精简
		PersonCreate create2=()->new Person();
		
		//构造方法的引用
		PersonCreate create3=Person::new;
		Person a=create3.getPerson();//无参方法执行了
		
		PersonCreate2 create4=Person::new;
		Person b=create4.getPerson("king", 12);//有参方法执行了
		
	}
}

案例

集合排序

public class Exercise1 {
	//集合排序
	//ArrayList<>
	public static void main(String[] args) {
		//需求:已知在一个ArrayList中有若干个person对象,将这些person对象按照年龄进行降序排序
		ArrayList<Person> list=new ArrayList<Person>();
		
		list.add(new Person("aa",12));
		list.add(new Person("bb",44));
		list.add(new Person("cc",52));
		
		//降序排序
		list.sort((o1,o2)->o2.age-o1.age);
		System.out.println(list);
		//[Person [name=cc, age=52], Person [name=bb, age=44], Person [name=aa, age=12]]
	}
}

TreeSet

public class Exercise2 {
	public static void main(String[] args) {
		//使用lambda表达式实现comparator接口,并实例化对象 
		//实现降序
		TreeSet<Person> set=new TreeSet<>((o1,o2)->o2.age-o1.age);
		
		set.add(new Person("aa",12));
		set.add(new Person("bb",44));
		set.add(new Person("cc",52));
	}
}

forEach

public class Exercise3 {
	public static void main(String[] args) {
		//集合遍历
		ArrayList<Integer> list=new ArrayList<>();
		
		Collections.addAll(list, 1,2,3,4,5,6);
		
		//将集合中的每一个元素都带入到方法accept中
		list.forEach(System.out::println);
		
		/*输出:
		 * 1
		 * 2
		 * 3
		 * 4
		 * 5
		 * 6
		 */
		//输出集合中所有的偶数
		list.forEach(a->{
			if(a%2==0)
				System.out.println(a);
		});
		
	}
}

removeif

public class Exercise4 {
	public static void main(String[] args) {
		//需求:删除集合中满足条件的元素
		ArrayList<Person> list=new ArrayList<Person>();
		
		list.add(new Person("aa",12));
		list.add(new Person("bb",44));
		list.add(new Person("cc",52));
		
		//删除年龄>45岁的人
		//lambda表达式实现
		//将集合中的每一个元素都带入到test方法中,如果返回值是true,则删除这个元素
		list.removeIf(a->a.age>45);
		System.out.println(list);
		//[Person [name=aa, age=12], Person [name=bb, age=44]]
	}
}

线程实例化

public class Exercise5 {
	public static void main(String[] args) {
		//需求:开辟一条线程。做一个数字的输出
		Thread t=new Thread(()->{
			for(int i=0;i<10;i++)
				System.out.println(i);
		});
		t.start();
	}
}

7.系统内置函数式接口

//系统内置的一些函数式接口
		//Predicate<T>:参数了返回值boolean
			//IntPredicate int->boolean
			//LongPredicate long->boolean
			//DoublePredicate double->boolean
		//Consumer<T>:参数T返回值void
			//IntConsumer int->void
			//LongConsumer long->void
			//DoubleConsumer double->void
		//Function<T,R>:参数了返回值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
			//DoubleToIntFunction doublt->int
			//DoubleTolongFunction double->long
		//Supplier<T>:参数无返回值T
		//UnaryOperator<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

		//Predicate<T>、Consumer<T>、Function<T,R>、Supplier<T>,比较常用

常见类型:

注意:在这些内置系统函数中,最多只有两个参数,如果有返回值,最后一个参数是返回值类型,如果入参多于两个,需要通过接口来实现lambda表达式

public class 常用内置函数式接口 {
	static void 例子(){
		//无入参,无返回
		Runnable r=()->System.out.println("11");
		r.run();//11
		//无参,有返回
		Supplier<Float> s=()->200f+300f;
		System.out.println(s.get());//500.0
		
		//1参,无返回
		Consumer<Date> c=(d)->System.out.println("当前时间:"+d.toString());
		c.accept(new Date());//当前时间:Thu Jun 11 14:34:09 CST 2020
		
		//1参,有返回
		Function<StringBuffer,String> f=sb->sb.reverse().toString();
		System.out.println(f.apply(new StringBuffer("abcd")));//dcba
		
		//2参,无返回
		BiConsumer<String,Integer> bc=(str,n)->{
			String ss="";
			for(int i=0;i<n;i++){
				ss+=str;
			}
			System.out.println(ss);
		};
		bc.accept("abc", 3);//abcabcabc
		
		//2参,有返回
		BiFunction<Integer,Integer,String> bif=(i,j)->i+""+j;
		System.out.println(bif.apply(1, 2));//12

	}
	public static void main(String[] args) {
		例子();
	}
}

8.流式运算

增强java.util下集合框架的功能。装饰者模式的思想(套一个新的接口马甲,功能更强-各种操作、支持链式风格、支持多种内置的lambda函数接口作为对象)。流式算法。视图。

Stream是处理数组和集合的API,Stream具有以下特点:

•	不是数据结构,没有内部存储
•	不支持索引访问
•	延迟计算
•	支持过滤,查找,转换,汇总等操作

首先需要弄清楚lambda的两个操作类型:中间操作终止操作

下面通过一个demo来认识下这个过程。

Stream st=Arrays.asList(1,2,3,4,5).stream().filter(x->{
   		System.out.print(x);
   		return  x>3;
   	});

当我们执行这段代码的时候,发现并没有任何输出,这是因为lambda表达式需要一个终止操作来完成最后的动作。 我们修改代码:

 Stream st=Arrays.asList(1,2,3,4,5).stream().filter(x->{
   		System.out.print(x);
   		return  x>3;
   	});
   	
   st.forEach(t-> System.out.print(t));

对应的输出结果是:

1234455

为什么会有这个输出呢?因为在filter函数的时候并没有真正的执行,在forEach的时候才开始执行整个lambda表达式,所以当执行到4的时候,filter输出之后,forEach也执行了,最终结果是1234455


对于Java中的lambda表达式的操作,可以归类和整理如下:

中间操作:链式风格

•	过滤 filter
•	去重 distinct
•	排序 sorted
•	截取 limit、skip
•	转换 map/flatMap
•	其他 peek

终止操作:无法用链式风格继续写。

•	循环 forEach
•	计算 min、max、count、 average
•	匹配 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
•	汇聚 reduce
•	收集器 toArray collect

举例:
在这里插入图片描述

public class Car {
	private String band;
	private float price;
	private float toSpeed;
	public String getBand() {
		return band;
	}
	public void setBand(String band) {
		this.band = band;
	}
	public float getPrice() {
		return price;
	}
	public void setPrice(float price) {
		this.price = price;
	}
	public float getToSpeed() {
		return toSpeed;
	}
	public void setToSpeed(float toSpeed) {
		this.toSpeed = toSpeed;
	}
	public Car(String band, float price, float toSpeed) {
		super();
		this.band = band;
		this.price = price;
		this.toSpeed = toSpeed;
	}
	@Override
	public String toString() {
		return "Car [band=" + band + ", price=" + price + ", toSpeed=" + toSpeed + "]";
	}
	
	
}

public class CarDemo {	
	static void test(Car[] car,HashMap map){
		
		//将数组转成集合
		List<Car> list=Arrays.asList(car);
		//过滤价格和速度为负数的车,并且按照toSpeed逆序排序,提取小集合,去重复
		Stream st=list.stream().filter((ss)->ss.getPrice()>0&&ss.getToSpeed()>0).sorted((o1,o2)->(int)(o2.getToSpeed()-o1.getToSpeed())).map(s->s.getBand()).distinct();
		st.forEach(System.out::println);
		Set<Integer> set=map.keySet();
		Stream st1=set.stream().sorted((o1,o2)->o1-o2).limit(3);
		st1.forEach(s->{
			System.out.println("第"+s+"名:"+map.get(s));
		});
	}
	
}
public class CarTest {
	public static void main(String[] args) {
		HashMap<Integer,Car> map=new HashMap<>();
		Car[] car=new Car[5];
		car[0]=new Car("宝马",230,200);
		car[1]=new Car("奔驰",246,456);
		car[2]=new Car("红旗",300,678);
		car[3]=new Car("丰田",500,987);
		car[4]=new Car("宝马",100,134);
		map.put(2, car[0]);
		map.put(1, car[1]);
		map.put(3, car[2]);
		map.put(4, car[3]);
		map.put(7, car[4]);
		CarDemo.test(car,map);
	}
}

结果:

丰田
红旗
奔驰
宝马
第1名:Car [band=奔驰, price=246.0, toSpeed=456.0]
第2名:Car [band=宝马, price=230.0, toSpeed=200.0]
第3名:Car [band=红旗, price=300.0, toSpeed=678.0]

9.闭包

public class ClosureDemo2 {
	public static void main(String[] args) {
		//在闭包中使用的变量一定是常量
		int a=10;
		Consumer<Integer> c=b->{
			System.out.println(b);
		};
		c.accept(a);//10
	}
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java后端指南

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值