Java Lambda表达式详细介绍

Java Lambda表达式详细介绍

Lambda简介

​Lambda​
​Lambda​
​Lambda​
​Lambda​
​Lambda​

Lambda基本语法

基本语法:​ ​(parameters) -> expression 或 (parameters) ->{ statements; }​ ​

  • parameters:类似方法中的形参列表,这里的参数是函数式接口里的参数。
  • ->:可以理解为 被用于
  • 方法体:可以是表达式,也可以是代码,是函数式接口里方法的实现。

代码示例:

// 返回给定字符串的长度(隐含return语句) 
(String str) -> str.length()

// 始终返回233的无参方法(隐含return语句) 
() -> 233

// 返回当前用户是否年龄大于20岁,返回一个boolean值(隐含return语句) 
(User user) -> user.getAge() > 20

// 包含多行表达式,需用花括号括起来,并使用return关键字返回
(int x, int y) -> { 
    int z = x * y; 
    return x + z; 
}

使用Lambda与传统写法对比

public class testMain {
    //执行Runnable方法
    public static void process(Runnable r){
        r.run();
    }

    public static void main(String[] args) {
        //使用Lambda
        Runnable r1=()-> System.out.println("Hello Lambda");
        //传统匿名类
        Runnable r2 = new Runnable(){
            public void run(){
                System.out.println("Hello World 2");
            }
        };
        //打印 "Hello World 1"
        process(r1);
        //打印 "Hello World 2"
        process(r2);
        //利用直接传递的 Lambda 打印 "Hello World 3"
        process(() -> System.out.println("Hello World 3"));
    }
}

Lambda表达式的基本使用

@FunctionalInterface
interface NoParameterNoReturn {
    //注意:只能有一个抽象方法
    void test();
}

//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
    void test(String a);
}

//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
    void test(int a, int b);
}

//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
    int test();
}

//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
    String test(String a);
}

//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
    int test(int a, int b);
}

具体使用见以下示例代码

//没有参数没有返回值
        NoParameterNoReturn noParameterNoReturn=()-> System.out.println("noParameterNoReturn");
        noParameterNoReturn.test();
        //没有参数但是有返回值
        NoParameterReturn noParameterReturn=()->40;
        System.out.println("noParameterReturn: "+ noParameterReturn.test());
        //一个参数没有返回值
        OneParameterNoReturn oneParameterNoReturn=(name)-> System.out.println("Hello :" +name);
        oneParameterNoReturn.test("张三");
        //一个参数和返回值
        OneParameterReturn oneParameterReturn=(name)-> "Hello: "+name;
        System.out.println("oneParameterReturn : "+ oneParameterReturn.test("李四") );
        //多参数没有返回值
        MoreParameterNoReturn moreParameterNoReturn=(a,b)-> System.out.println("a+b= "+(a+b));
        moreParameterNoReturn.test(10,20);
        //多参数和返回值
        MoreParameterReturn moreParameterReturn=(a,b)-> a+b;
        System.out.println("moreParameterReturn: "+ moreParameterReturn.test(20,40));

输出结果如下:

Lambda 受检异常处理

简介

​Lambda​
​Lambda​

代码示例

以一个简单代码为例,将10与List中每个元素相除并打印出结果

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6);
        integers.forEach(i -> System.out.println(50 / i));

这样看是不会有问题的,代码简洁。但是如果List中包含元素​ ​0​ ​​,那么就会抛出异常:​ ​ArithmeticException: / by zero​ ​有经验的小伙伴可能会立马给出解决方案,使用传统的try-catch来处理异常,代码如下:

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 0);
        integers.forEach(i -> {
            try {
                System.out.println(10 / i);
            } catch (ArithmeticException e) {
                System.err.println( "Arithmetic Exception occured : " + e.getMessage());
            }
        });

使用try-catch解决了问题,但是失去了lambda表达式的精简,代码变得臃肿,想必并不是完美的解决方案。对于一些强迫症老哥来说,这种代码是绝对不能存活的,所以我们需要如下的解决方案。

解决方案

我们将会对抛出异常的函数进行包装,使其不抛出受检异常如果一个​ ​FunctionInterface​ ​​的方法会抛出受检异常(比如​ ​Exception​ ​​),那么该​ ​FunctionInterface​ ​​便可以作为会抛出受检异常的 Lambda 的目标类型。我们定义如下一个​ ​FunctionInterface​ ​:

@FunctionalInterface
interface UncheckedFunction<T, R> {
    R apply(T t) throws Exception;
}

首先我们定义一个​ ​Try​ ​类,它的consumerWrapper方法:

public class Try {

    public static <T, E extends Exception> Consumer<T> consumerWrapper(Consumer<T> consumer, Class<E> clazz)  {

        return i -> {
            try {
                consumer.accept(i);
            } catch (Exception ex) {
                try {
                    E exCast = clazz.cast(ex);
                    System.err.println(
                            "Exception occured : " + exCast.getMessage());
                } catch (ClassCastException ccEx) {
                    throw ex;
                }
            }
        };
    }
}

然后在原先的代码中,我们使用​ ​Try.consumerWrapper​ ​方法来对会抛出受检异常的 Lambda 进行包装:

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 0);
        integers.forEach(
                Try.consumerWrapper(
                        i -> System.out.println(50 / i),
                        ArithmeticException.class));

此时,我们便可以选择是否去捕获异常(​ ​RuntimeException​ ​)。这种解决方法下,我们一般不关心抛出异常的情况 。比如自己写的小例子,抛出了异常程序就该终止;或者你知道这个 Lambda 确实 100% 不会抛出异常。

如果您觉得本文不错, 欢迎关注,点赞,收藏支持 ,您的关注是我坚持的动力!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值