lambda表达式

本文介绍了Java8的三大核心特性:Lambda表达式的使用,包括其语法糖如可选类型声明、参数括号和大括号,以及在函数式接口中的应用。方法引用作为Lambda的优化形式,分为静态、实例和构造方法引用。最后,文章讲解了Stream流的概念,如何获取流以及其特点,并展示了如何在实际操作中简化集合处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

lambda表达式是Java8的新特性,它免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力,它允许把一个函数作为方法的参数(函数作为参数传递进方法中)使用lambda表达式可以让代码更加的简洁紧凑,符合未来函数式编程的趋势。

普通方式、匿名方式和lambda分别实现线程

//普通方法
public class test2 implements Runnable{ 
	public static void main(String[] args) {
		test2 te = new test2();
		Thread th = new Thread(te);
		th.start();
	}
	@Override
	public void run() {
		System.out.println("start to run");
	}
}

//匿名方法
public class test2{ 
	public static void main(String[] args) {
		Thread th = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("start to run");
			}
		});
		th.start();
	}
}

//lambda方式
public class test2 {  
	public static void main(String[] args) {
		Runnable run = ()->System.out.println("start to run");
		Thread th = new Thread(run);
		th.start();
	}
	}
}

结论:使用匿名的方式省去了创建对象和重写方法的步骤,而lambda则是对匿名方式的一种优化,简化了匿名方式的写法,使得代码更加简洁紧凑。

lambda的重要特征

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。例如:x->2*x
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。例如:(x, y) -> x – y
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。例如:(int x, int y) -> x + y
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值
示例代码
public interface SingleNum {
int single(int i);
}

@FunctionalInterface
public interface AddOperation {
	int operation(int a,int b);
	//boolean operaion(int a);  //添加后测试类报错:The target type of this expression must be a functional interface
}
public class test1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		test1 t = new test1();
		System.out.println("single param test result:"+t.singleFun(2, i->i+1));
		System.out.println("double param test result:"+t.addOperation(3, 5, (a,b)->a+b));
		
	}
	
	public static int singleFun(int i,SingleNum a) {
		return a.single(i);
	}
	
	public static int addOperation(int a,int b,AddOperation c) {
		return c.operation(a, b);
	}
}

函数式接口

lambda通过使用函数式接口来简化代码,那么什么是函数式接口呢?

函数式接口,简单来说,就是只包含一个方法的接口。同时,函数式接口可以用注解**@FunctionalInterface**来修饰,这样可以实时监测你写的接口是否符合函数式接口的要求。

常用的函数式接口有哪些呢?
  1. Comparator,属于java.util包,有且仅有一个抽象方法:int compare(T o1, T o2);
  2. Suppiler,生产式接口,抽象方法:T get();
  3. Consumer,消费型接口,抽象方法:void accept(T t);
  4. Predicate,断言型接口
  5. Function,函数型接口,抽象方法:R apply(T t);、一般结合andThen()方法使用。

示例

//Comparator
	public static Comparator<String> getComparator(){
    return (o1,o2)->o1.length()-o2.length();
	}
	public static void main(String[] args) {
		String arr[]={"a","bb","dddd","ccc"};
		System.out.println(Arrays.toString(arr));
        Arrays.sort(arr,getComparator());  //Arrays的sort方法使用了Comparator函数作为参数
        System.out.println(Arrays.toString(arr));
	}

//Suppiler
public static void main(String[] args) {
		System.out.println(new SupplierTest().appendString(()->"hello ", "world"));
	}
	public static  String appendString(Supplier<String> sub,String s) {
		return sub.get()+s;
	}

//Consumer
public static void main(String[] args) {
		ComsumerTest te = new ComsumerTest();
		te.consumerFun((a)->System.out.println("消费了"+a), 2);
	}
	public static void consumerFun(Consumer<Integer> com,Integer i) {
		 com.accept(i);
	}

//Predicate
	public static void main(String[] args) {
		PredicateTest te = new PredicateTest();
		boolean b = te.predicate((a)->{
			if(a>0) return true;
			else return false;
		}, 3);
		System.out.println(b);
	}
	public static boolean predicate(Predicate<Integer> p,int i) {
		return p.test(i);
	}

//Function
	public static void main(String[] args) {
		FilterTest te = new FilterTest();
		String str= te.filter((s)->s.trim(), " hello  world");
		System.out.println(str);
		String st = te.appendStr((s)->s+"haha",(a)->a.trim(), "  hello wolrd  ");
		System.out.println(st);
	}
	public static String filter(Function<String,String> f,String s) {
		return f.apply(s);	
	}
	public static String appendStr(Function<String,String> f,Function<String,String> f2,String s) {
		 return f.andThen(f2).apply(s);  //意思是String s=fun.aplply(s)+"haha",String s1=fun2.apply(s)
	}

方法引用

方法引用是指类名或者实例对象通过 ‘::’ 符号直接引用方法,除了调用动作外,没有其他任何多余的动作
其实它也是lambda的另外一种表现形式或者说是lambda格式的一种优化。

使用场景

我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它。

方法引用的分类
  1. 静态方法引用。格式:类名::静态方法
  2. 实例方法引用。格式:实例对象::实例方法
  3. 对象方法引用。格式:类名::实例方法
  4. 构建方法引用。格式:类名::new

举例

//静态方法引用
public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer> li = Arrays.asList(1,2,3,4);
		li.sort((a,b)->Integer.compare(a, b)); //普通的lambda表达式
		li.sort(Integer::compare);   //方法引用
	}

//实例方法引用
	public static void main(String[] args) {
		ReferenceTest2 test = new ReferenceTest2();
        User user = new User("欧阳峰",32);
        Supplier<String> supplier = () -> user.getName();
        System.out.println("Lambda表达式输出结果:" + supplier.get());
        
        Supplier<String> supplier2 = user::getName;
        System.out.println("实例方法引用输出结果:" + supplier2.get());
    }
@Data
class User {
    private String name;
    private Integer age;
}

//构造方法引用
public static void main(String[] args) {
		Supplier<List<Integer>> userSupplier = () -> new ArrayList<>();
		List<Integer> li = userSupplier.get();
	
		Supplier<List<Integer>> userSupplier1 = ArrayList::new;
		List<Integer> li2 = userSupplier1.get();
    }

Stream流

Stream流是Lambda的衍生物,能够简化集合和数组的操作,关注的是做什么,而不是怎么做

获取流的方式
  • 对于Collection集合,有一个默认的方法stream方法获取流
  • Stream接口中也有方法of来获取流
Stream流的特点

属于管道流,只能被消费一次,第一个Stream流使用完毕,数据会流向下一个Stream流,前一个就会关闭

示例

public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer> li = Arrays.asList(1,2,3,4,5,9,8);
		List<String> li2 = Arrays.asList("a","bb","dddd","ccc");
		//截取,排序、过滤和打印
	li.stream().limit(5).sorted().filter(a->a!=0).forEach(System.out::println);
	
	System.out.println("--------------");
	//过滤、排序和打印
	li2.stream().filter(a->!a.isEmpty()).sorted().forEach(System.out::println);
	//获取最大值
	Optional<Integer> max = li.stream().max((a,b)->{return b-a;});
	Integer i = max.get();
	System.out.println(i);
	}

总结

1、哪里有函数式接口,哪里就能用lambda表达式
2、当涉及到匿名函数或者方法返回的是一个函数式接口时,可以用lambda表达式
3、方法引用的前提是;对象和方法都已经存在\类和方法都存在
4、方法引用是Java8的新特性,它是在lambda的基础上才能够使用,脱离了lambda,则无意义,在某些条件下,是对lambda格式的另一种写法,但是本人不建议使用这个特性,可读性不高,也不便于编程。
5、Stream流也是Java8的新特性,它是流式函数,管道中从前往后执行,最终结束,使用它,方便我们进行流式编程,使得代码更加的优雅整洁,同时,它也是在lambda的基础上进行的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值