你真的学会了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表达式:过关斩将:使用场景》
二、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循环中遍历keys或values。
System.out.println();
System.out.println("方法二 在for-each循环中遍历keys或values");
//遍历keys and value
for(String key:map.keySet()){
System.out.println("key:"+key+",value:"+map.get(key));
}
//只遍历values
System.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