java学习(lambda表达式)

初识lambda表达式

public class Lambda {
    // () -> {}
    public static void main(String[] args){
        String[] strings = new String[3];
        strings[0] = "bc";
        strings[1] = "a";
        strings[2] = "def";
        for(String str : strings){
            System.out.println(str);
        }
        // sort函数的第二个参数需要一个实现了comparator接口的类的对象
        Arrays.sort(strings, new LengthComparator());
        for(String str : strings){
            System.out.println(str);
        }
        // 下方lambda表达式中的参数列表(String first, String second)的类型名String,
        // 若能从上下文推断出来则不需指定
        // 若参数只有一个,且类型可以由上下文推断出来,则小括号也可以省略
        // 若没有参数,小括号不能省略
        // 这是expression lambda,不需要写return,直接将该表达式的结果返回
        Arrays.sort(strings, (String first, String second) -> Integer.compare(second.length(), first.length()));
        for (String str : strings) {
            System.out.println(str);
        }

        // 若需要写多行则用{}将后面的表达式括起来  
        // 这是statement lambda,return要显示的写出来
        Arrays.sort(strings, (String first, String second) -> {
            if (first.length() > second.length()) {
                return 1;
            } else if (first.length() == second.length()) {
                return 0;
            } else {
                return -1;
            }
        });
        for (String str : strings) {
            System.out.println(str);
        }


    }

}

class LengthComparator implements Comparator<String>{
    public int compare(String first, String second) {
        return Integer.compare(first.length(), second.length());
    }
}

Functional Interface

如果一个借口仅有一个抽象方法,就称为函数式接口,比如Runnable,Comparator,在任何需要Functional Interface的地方,都可以用lambda表达式

上面代码中,

Arrays.sort(strings, (String first, String second) -> Integer.compare(second.length(), first.length()));

这里,sort()的第二个参数应该是一个Comparator的对象,而Comparator是一个Functional Interface,因此可以直接传入lambda表达式,在调用该对象的compare(),就是执行该lambda表达式的语句体
如果lambda表达式的语句体会抛出异常,则对应的Functional Interface的抽象方法必须抛出该异常,否则就需要在lambda表达式中显示的捕获该异常

Runnable r = () -> {
    System.out.println("--");
    try{
        Thread.sleep();
    } catch (InterruptedException e) {}
};

如上代码中要捕获异常是因为Runnable接口的唯一的方法run方法没有抛出该异常

Method Reference

以下两种表达方式等价

(x) -> System.out.println(x)
System.out::println

其中第二行就是Method Reference

Method Reference由三种形式
1. object::instanceMethod

System.out::println
(x) -> System.out.println(x)
  1. Class::staticMethod
Math::pow 
(x, y) -> Math.pow(x, y)
  1. Class::instanceMethod
String::compareToIgnoreCase
(s1, s2) -> s1.compareToIgnoreCase(s2)

其中,第三种方式会将第一个参数作为对象,调用方法,将其他的参数作为方法的参数使用

变量作用域

如下代码

public class Lambda{
    public static void main(String[] args){
        repeatMessage("Hello", 5);
    }

    public static void repeatMessage(String text, int count) {
        Runnable r = () -> {
            for(int i = 0;i<count;i++){
                System.out.println(text);
                Thread.yield();
            }
        };
        new Thread(r).start();
    }
}

注意看lambda表达式中的变量count和text,它们并没有在lambda 表达式中被定义,而是repeatMessage方法中的变量。而在yield之后,repeatMessage返回了,此时参数变量已经消失了,那么lambda如何保留text和count的呢?

我们可以说,lambda捕获了text和count两个值,在lambda表达式中,不能修改捕获的值。
比如,在lambda中加入一句

count--;

会报错!

另外,lambda表达式中不允许声明一个和局部变量同名的参数或者局部变量

在lambda中使用this时,this是它所在方法的类的对象

参考:
https://my.oschina.net/fhd/blog/419892
http://www.jb51.net/article/81204.htm

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值