你真的学会了Lambda表达式了吗?一篇让你学废了不香么 - 第417篇

 对于Lambda在很久就写过一个小系列了,但真正在使用或者看到源码的时候,却还是不懂,脱离实际代码学习技术,都是在耍流氓。

         那我们这一节课,一方面是对于之前的系列会做一个总结,另外就是会通过一些示例来进一步的悟透Lambda表达式

一、Lambda总结

1.1 Lambda定义

  Lambda表达式是一个匿名函数,允许把函数作为一个方法的参数传递到方法中(函数作为参数传递进方法)。

λ->(α、β,这是数学中定义常量、未知数的),读音:lan b(m) da(兰亩达)['læ;mdə]。(啊法、贝塔、兰亩达,^_^,很好记有木有)

1.2 Lambda语法

         Lambda 表达式的语法格式如下:

(parameters) ->expression;

或者:

(parameters) ->{statements;}

         以下是lambda表达式的重要特征:

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

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

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

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

1.3 Lambda原理

         核心点就是接口实现了@FunctionalInterface,使用了@FunctionalInterface注解之后,只能定义一个方法,否则编译器会报错(但是允许定义默认方法和静态方法)。

更详细的可以看历史文章,关注公众号「SpringBoot」,回复关键词「lambda」,查看Lambada表达式的系列文章:

Java8新特性:Lambda表达式:小试牛刀

Java8新特性:Lambda表达式:过关斩将:使用场景

Java8新特性:Lambda表达式:摸摸里面

二、Lambda例子分析

2.1 优化线程代码

         以前我们使用线程可能是这么使用的:

new Thread(new Runnable(){    @Override    public void run() {        System.out.println("thread run");    }}).start();

         使用lambda可以这么使用:

new Thread(()->{     System.out.println("thread run");}).start();

         我们在前面说到可以使用Lambda是注解了@FunctionalInterface,看下接口Runnable:

         上面的代码只有一行代码,可以再次进行优化写法:

new Thread( ()->System.out.println("thread run")).start();

说明:如果有多行代码,那么就不能这样子简写了。

2.2 Arrays.sort排序优化

         在代码中,我们会使用Arrays.sort对数据进行排序,Arrays.sort是可以对数组、列表集合进行排序的,很多时候会使用的到。那么以前我们的写法是这样子的:

Integer[] playerScore = {89, 100, 77, 90,  86};// 使用匿名内部类根据 分数从低到高进行排序Arrays.sort(playerScore,new Comparator<Integer>(){    /**     *     * @param o1 o1是后一个数,第一次比较就是100     * @param o2 o2是前一个数,第一次比较就是89     * @return 比较的返回值,第一次就是100.compareTo(89),返回值是1     */    @Override    public int compare(Integer o1, Integer o2) {        return o1.compareTo(o2);    }});for(Integer score:playerScore){//输出结果:77,86,89,90,100,    System.out.print(score);}

         使用lambda可以这么使用:



Arrays.sort(playerScore,(Integer o1,Integer o2)->o1.compareTo(o2) );

         类型Integer也可以去掉优化成:

Arrays.sort(playerScore,(o1,o2)->o1.compareTo(o2) );

         再次优化还可以这么写:

Arrays.sort(playerScore,Comparator.comparing(Integer::intValue));

         其中Integer::intValue(方法引用使用一对冒号 ::),就是Integer类中的方法intValue:

         

从高到底呢?

Arrays.sort(playerScore,Comparator.comparing(Integer::intValue).reversed());

         对于compareTo从高到底就只需要调整下o1和o2的位置了:

Arrays.sort(playerScore,(o1,o2)->o2.compareTo(o1));

2.3 List遍历

         在java8之前对于List的遍历使用for循环的方式,在java8之后遍历打印就显得很简单了:

List<String> languages = Arrays.asList("java","php","python");//java8 之前System.out.println("String str:languages ->");for(String str:languages){    System.out.print(str+",");}System.out.println("\n\nint i=0;i<languages.size();i++ ->");for(int i=0;i<languages.size();i++){    System.out.print(languages.get(i)+",");}//java8之后System.out.println("\n\nlanguages.forEach ->");languages.forEach(language-> System.out.print(language+","));

2.4 Map遍历

         对于Map的遍历应该是很常用的,使用Lambda遍历代码将会更简单:

Map<String,Object> map = new HashMap<>();map.put("author","悟纤");map.put("age","18");map.put("blog","微信公众号「SpringBoot」");map.put("hobby","美女");//java8之前的方式:方法一 在for-each循环中使用entries来遍历(常用)System.out.println("方法一 在for-each循环中使用entries来遍历:");for(Map.Entry<String,Object> entry:map.entrySet()){    System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());}//java8之前的方式:方法二 在for-each循环中遍历keysvaluesSystem.out.println();System.out.println("方法二 在for-each循环中遍历keys或values");//遍历keys and valuefor(String key:map.keySet()){    System.out.println("key:"+key+",value:"+map.get(key));}//只遍历valuesSystem.out.println("----------------");for(Object value:map.values()){    System.out.println("value:"+value);}//java8之前的方式:方法三使用Iterator遍历System.out.println();System.out.println("方法三使用Iterator遍历");Iterator<Map.Entry<String,Object>> entryIterator = map.entrySet().iterator();while(entryIterator.hasNext()){    Map.Entry<String,Object> entry =  entryIterator.next();    System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());}//java8之后的方式System.out.println("\njava8之后的方式");map.forEach((key,value)->System.out.println("key:"+key+",value:"+value) );

画外音:一不小心教会了你Map的4中遍历。

         对于对于Map如果没获取到key的话,我们会有一个默认值的显示,比如显示为“-”或者“无”,在java8这样的需求就简单的一匹:

//java8之前没有获取到key显示默认值为"-"Object birthday = map.get("birthday");if(birthday == null){    birthday = "-";}System.out.println("birthday:"+birthday);//java8之后的方式System.out.println("birthday:"+map.getOrDefault("birthday","-"));

当然这个方法和Lambda表达式没有太大关系,这个源码你也能实现:

说明:这个直接是Map接口中的方法,在jdk1.7之前接口上是不能有方法的实现的,但是在jdk1.8+之后,对于接口可以实现default方法了。

结束语

         原本想介绍更多的例子的,但发现Lambda单单自己的话,还是比较弱的,需要配合上Stream才能产生更大的效果,下一节咱们就看看Stream到底是何方神圣。


购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287