Java lambda表达式

java8中一个非常重要的特性就是lambda表达式,我们可以把它看成是一种闭包,它允许把函数当做参数来使用,是面向函数式编程的思想,一定程度上可以使代码看起来更加简洁。例如以前我们使用匿名内部类来实现代码:

//匿名内部类写法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("内部类写法");
            }
        }).start();

使用lambda则更加简洁:

 //lambda 写法
        new Thread(() -> System.out.println("lambda写法")).start();    

1、lambda表达式语法

1.1lambda表达式的一般语法

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}

这是lambda表达式的完全式语法,后面几种语法是对它的简化。

1.2单参数语法

param1 -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}

当lambda表达式的参数个数只有一个,可以省略小括号
例如:将列表中的字符串转换为全小写

List<String> proNames = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
List<String> lowercaseNames1 = proNames.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());

1.3单语句写法

param1 -> statment

当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号

例如:将列表中的字符串转换为全小写

List<String> proNames = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
List<String> lowercaseNames2 = proNames.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());

1.4方法引用写法

表达式:

Class or instance :: method

例如:将列表中的字符串转换为全小写

List<String> proNames = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
List<String> lowercaseNames3 = proNames.stream().map(String::toLowerCase).collect(Collectors.toList());

2、lambda表达式可使用的变量

将为列表中的字符串添加前缀字符串:

String waibu = "lambda :";
List<String> proStrs = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
List<String>execStrs = proStrs.stream().map(chuandi -> {
Long zidingyi = System.currentTimeMillis();
return waibu + chuandi + " -----:" + zidingyi;
}).collect(Collectors.toList());
execStrs.forEach(System.out::println);

输出:

lambda :Ni -----:1474622341604
lambda :Hao -----:1474622341604
lambda :Lambda -----:1474622341604

变量waibu :外部变量
变量chuandi :传递变量
变量zidingyi :内部自定义变量

lambda表达式可以访问给它传递的变量,访问自己内部定义的变量,同时也能访问它外部的变量。
不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。当在表达式内部修改waibu = waibu + " ";时,IDE就会提示你:Local variable waibu defined in an enclosing scope must be final or effectively final.编译时会报错。因为变量waibu被lambda表达式引用,所以编译器会隐式的把其当成final来处理。以前Java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。现在java8对这个限制做了优化,可以不用显示使用final修饰,但是编译器隐式当成final来处理。

3、lambda表达式中的this概念

在lambda,this不是指向lambda表达式产生的那个对象,而是声明它的外部对象。例如:

public class WhatThis {

     public void whatThis(){
           //转全小写
           List<String> proStrs = Arrays.asList(new String[]{"Ni","Hao","Lambda"});
           List<String> execStrs = proStrs.stream().map(str -> {
                 System.out.println(this.getClass().getName());
                 return str.toLowerCase();
           }).collect(Collectors.toList());
           execStrs.forEach(System.out::println);
     }

     public static void main(String[] args) {
           WhatThis wt = new WhatThis();
           wt.whatThis();
     }
}

输出:

com.wzg.test.WhatThis
com.wzg.test.WhatThis
com.wzg.test.WhatThis
ni
hao
lambda

4、方法引用

本人认为是进一步简化lambda表达式的声明的一种语法糖。
前面的例子中已有使用到: execStrs.forEach(System.out::println);

4.1 对象::实例方法,将lambda的参数当做方法的参数使用

objectName::instanceMethod
示例:

Consumer<String> sc = System.out::println;
//等效
sc.accept("618, 狂欢happy");
Consumer<String> sc2 = (x) -> System.out.println(x);        

4.2 类::静态方法,将lambda的参数当做方法的参数使用

ClassName::staticMethod
示例:

//ClassName::staticMethod  类的静态方法:把表达式的参数值作为staticMethod方法的参数
        Function<Integer, String> sf = String::valueOf;
        //等效
        Function<Integer, String> sf2 = (x) -> String.valueOf(x);
        String apply1 = sf.apply(61888);

4.3 类::实例方法,将lambda的第一个参数当做方法的调用者,其他的参数作为方法的参数

ClassName::instanceMethod
示例:

//ClassName::instanceMethod  类的实例方法:把表达式的第一个参数当成instanceMethod的调用者,其他参数作为该方法的参数
        BiPredicate<String, String> sbp = String::equals;
        //等效
        BiPredicate<String, String> sbp2 = (x, y) -> x.equals(y);
        boolean test = sbp.test("a", "A");

5、构造函数

无参的构造方法就是类::实例方法模型,如:

  Supplier<User> us = User::new;
        //等效
        Supplier<User> us2 = () -> new User();
        //获取对象
        User user = us.get();

当有参数时:

//一个参数,参数类型不同则会编译出错
        Function<Integer, User> uf = id -> new User(id);
        //或加括号
        Function<Integer, User> uf2 = (id) -> new User(id);
        //等效
        Function<Integer, User> uf3 = (Integer id) -> new User(id);
        User apply = uf.apply(61888);

        //两个参数
        BiFunction<Integer, String, User> ubf = (id, name) -> new User(id, name);
        User 狂欢happy = ubf.apply(618, "狂欢happy");

6、总结

java8引入lambda表达式是接收了函数式编程语言的思想,例如scala之类的,它将函数视为一等公民,可以使用高阶函数等。
和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
和过程化编程相比,函数式编程里函数的计算可随时调用。
写在最后,lambda表达式可以使代码看起来简洁,但一定程度上增加了代码的可读性以及调试的复杂性,所以在使用时应尽量是团队都熟悉使用,要么干脆就别用,不然维护起来是件较痛苦的事。

参考:

https://www.cnblogs.com/kingsonfu/p/11047116.html

https://www.cnblogs.com/aoeiuv/p/5911692.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容