Java8新特性:Lambda表达式详解及四大函数式接口

Lambda 表达式是Java8以后的新特性,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑,相应的带来了新的学习成本。

Lambda语法特征主要有以下四点:

1. 可选的类型声明:
不需要声明参数类型,编译器可以统一识别参数值。如:

() -> 15

2. 可选的参数圆括号:
一个参数无需定义圆括号,但多个参数需要定义圆括号。如:

x -> 2 * x 

3. 可选的大括号:
如果主体包含了一个语句,就不需要使用大括号。如:

(x, y) -> x – y  

4. 可选的返回关键字:
如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

(int x, int y) -> { return x * y; };

Lambda表达式实现的原理:

要实现Lambda表达式,必须先有函数式接口,那怎样才能定义一个函数式接口呢,接口需具有唯一的一个抽像方法,可以定义默认方法、静态方法、定义java.lang.Object里的public方法,再IDE中可以使用@FunctionalInterface注解修饰不报错即可。至于为什么只能有一个没有实现的方法,看完下面的实现原理就能很好的明白。

@FunctionalInterface
interface Print<T> {
    public void print(T x);
    default void doSomeMoreWork1(){
        // Method body
    }
    static void printHello(){
        System.out.println("Hello");
    }
    @Override
    boolean equals(Object obj);
}

在编译器由Java编译成class是,会把包含Lambda表达式的方法按照Java自己的规则生成一个方法,而这个方法的参数就是Lambda -> 前的参数,方法内的处理逻辑即使 -> 后的内容,所以如果函数式接口有一个以上的抽象方法就会导致编译器不知道该让谁去实现Lambda表达式。

我们源码写的是这样的。

public class LambdaTest {
    public static void printString(String s, Print<String> print) {
        print.print(s);
    }
    public static void main(String[] args) {
        printString("test", (x) -> System.out.println(x));
    }
}

@FunctionalInterface
interface Print<T> {
    public void print(T x);
}

经过编译后通过Class文件反编译回Java是这样的

public class LambdaTest {
    public static void PrintString(String s, Print<String> print) {
        print.print(s);
    }

    public static void main(String[] args) {
        PrintString("test", new LambdaTest$$Lambda$1());
    }

    private static void lambda$main$0(String x) {
        System.out.println(x);
    }

    static final class LambdaTest$$Lambda$1 implements Print {
        public void print(Object obj) {
            LambdaTest.lambda$main$0((String) obj);
        }
        private LambdaTest$$Lambda$1() {
        }
    }

}

@FunctionalInterface
interface Print<T> {
    public void print(T x);
}

这里是摘自https://blog.csdn.net/jiankunking/article/details/79825928,看原文更容易理解。

四大内置核心函数式接口

1. Consumer:消费型接口 void accept(T t);
消费型接口就是传进去参数经过表达式处理,没有返回值。

public void test(){
    shopping(1000,(x)-> System.out.println("今天购物发了"+x+"元"));
}
public  void shopping(double money, Consumer<Double> con){
	con.accept(money);
}

2. Supplier :供给型接口 T get();
供给型接口就是无中生有,不传参经过表达式处理返回值,比如生成随机数

public void test2(){
	List<Integer> numList=getNumList(3,()->(int)(Math.random()*10));
}
   
public List<Integer> getNumList(int num, Supplier<Integer> sup){
    List<Integer> list=new ArrayList<>();
    for (int i=0;i<num;i++){
        Integer n=sup.get();
        list.add(n);
    }
    return list;
}

3. Function<T,R>: 函数型接口 R apply(T t);
函数型接口有传参有返回值。

public void test3(){
   String newStr= handlerStr("helloworld",(str)->str.substring(3,6));
   System.out.println(newStr);
}

public String handlerStr(String str, Function<String,String> fun){
    return fun.apply(str);
}

4. Predicate: 断言型接口 boolean test(T t)
返回true或者false

	public void test4(){
        List<String> list= Arrays.asList("idea","eclipse","predicate","function");
        List<String> returnList= filterStr(list,(str)->str.length()>4);  
    }
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> newList=new ArrayList<>();
        for (String str:list) {
            if(pre.test(str)){
               newList.add(str);
            }
        }
        return newList;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦里藍天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值