前言:
Lambda表达式初体验:
Lambda表达式的转变过程:
Lambda表达式的优势:
Lambda表达式的使用:
未完待续:
本人大学读的是电子信息工程,和大部分人一样毕业后没有从事本专业的工作,2014年毕业后先后干过:
打算学习一下大数据(python)不要问我为什么做的这么杂,因为世界唯一不变的就是变。
半路出家做java开发已经两年了,之前一段日子一直是浑浑噩噩,最近看了一些书,《人性的弱点》,《软技能》,《自控力》对我启发颇多,决定每个星期更新一篇技术博客,来总结一下学到的知识,也分享给大家,希望对大家有所帮助,好了,废话已经说了一堆了正式开始进入正题。
第一次在代码中体验lambda表达式是在使用策略模式中使用匿名类的时候,idea编译器竟然对我的其中一个函数调用的代码灰色字体提示,但我自认为写的非常的规范:
//真是代码是用策略模式 对不同的锁动态密码使用不同的算法
//由于真实的代码比较复杂,用《java8实战》中的代码代替一下,见谅
//这个例子是用策略模式 对不同类型的苹果进行筛选
/**
* 苹果类
*/
public class Apple {
private String color;
private int weight;
public Apple(String color, int weight) {
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
/********************************************************/
/**
* 苹果筛选接口
*/
public interface ApplePredicate {
boolean test (Apple apple);
}
/********************************************************/
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 苹果过滤器类
*/
public class AppleFilter {
//苹果过滤器
public List filterApples(List apples, ApplePredicate predicate) {
List result = new ArrayList<>(apples.size());
for (Apple apple : apples) {
if (predicate.test(apple)) {
result.add(apple);
}
}
return result;
}
//摘苹果
public static List pickApples(int num) {
List apples = new ArrayList<>(num);
Random random = new Random(2);
for (int i = 0; i < num; i++) {
String randomColor = random.nextBoolean() ? "red" : "green";
int randomWeight = random.nextInt(100) + 200;
Apple apple = new Apple(randomColor, randomWeight);
apples.add(apple);
}
return apples;
}
//打印苹果信息
public static void printApples(List apples) {
System.out.println("Apples nums:" + apples.size());
for (int i = 0; i < apples.size(); i++) {
if (i % 5 == 0) {
System.out.println();
}
System.out.print(apples.get(i) + ",");
}
System.out.println();
System.out.println("-----------------------------------------------------------");
}
//测试
public static void main(String[] args) {
int num = 100;
//农民伯伯采摘了100个苹果
List apples = pickApples(num);
printApples(apples);
AppleFilter filter = new AppleFilter();
//收购商说要红苹果,让农民伯伯把苹果放入机器筛选红苹果出来
List applesResult1 = filter.filterApples(apples, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return "red".equals(apple.getColor());
}
});
printApples(applesResult1);
}
}
What?你这是凭什么给我报啊(程序员一般都对自己比较自信!),怀着疑惑的心情Alt+Enter查看到底是什么问题?
看到了这样的一个提示:
Replace with lambda?lambda是什么鬼,无知的我,处于好奇,点击了它,我去!
神奇的事情发生了,眼前代码脱胎换骨:
我的代码摇身一变,这是减肥了?!
从匿名类 new ApplePredicate() { @Override public boolean test(Apple apple) { return "red".equals(apple.getColor()); } } 到lambda apple -> "red".equals(apple.getColor())
我的代码你到底经历了什么?
带着这样的疑问,让我们一起来一探究竟把。
正如你所见,你仔细观察一下这个苗条的姑娘(lambda表达式),你就会发现她还是原来的她,
apple 对应匿名函数中 test(Apple apple)方法的参数,
"red".equals(apple.getColor()) 对应test(Apple apple)的方法内容
姑娘就是系了根腰带 (->),而且变瘦了(省略了其他部分)
好了让我们来看看lambda的真面目吧!
lambda由三部分组成:
来看几个有效的lambda表达式:
到这里有人可能会说这个匿名函数没什么大的区别嘛,干嘛要整个lambda出来啊,这不是找麻烦啊。
兄dei!不要急,这就来讲讲lambda的优势。
还是先看个例子,筛选好了以后,收购商发现这里面混杂这小苹果,他觉得小苹果不能以一样的价格收,于是他又提出来要把240克一下的苹果全部剔除出来,以更便宜的价格收购。农名伯伯和无奈啊,只能照做了,按照匿名的方式这回应该这么做:
//农民伯伯心不甘情不愿的筛选出了小苹果
List applesResult2 = filter.filterApples(apples, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 240;
}
});
这时,农民伯伯气不过啊,凭什么你要大就大啊,于是他偷偷摸摸的又把大的苹果自己拿出来,打算自己去卖。
//农民伯伯挑出了绿苹果和大苹果,打算自己卖
List applesResult3 = filter.filterApples(apples, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
return apple.getWeight() > 280 || "green".equals(apple.getColor());
}
});
到这个时候,相信大家已经发现,这么做,里面有很多的代码是重复的,多余的,那如果使用lambda呢?会是神马效果?
//农民伯伯心不甘情不愿的筛选出了小苹果
List applesResult2 = filter.filterApples(apples, apple -> apple.getWeight() > 240);
//农民伯伯挑出了绿苹果和大苹果,打算自己卖
List applesResult3 = filter.filterApples(apples, apple -> apple.getWeight() > 280 || "green".equals(apple.getColor()));
一下子就变成了最精简的代码了,程序员估计都喜欢苗条的把,哈哈,没错lambda表达式去除了匿名函数啰嗦的部分变得更加的精简和直观。
可能看到这里,大家对lambda的优点有所了解,但是可能对到底怎么了使用lambda表达式还是一头雾水。来来来,别急,上干货了,
首先我们先要明确 Lambda表达式是使用在函数式接口上的, 什么是函数式接口?函数式接口就是只定义一个抽象方法的接口(没有,或多个都不行)。Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现, 并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现的实例),
在实际代码中的使用来给个例子:
常常会遇到读取文本的代码,比如这样:
//读取文本的第一行
public static String processFile() throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader("data.txt"))) {
return br.readLine();
}
}
直接这样写有点low,如果需要读两行,三行,n行呢?我们先来参数化
@FunctionalInterface
public interface BufferedReaderProcessor {
String process(BufferedReader b) throws IOException;
}
public static String processFile(BufferedReaderProcessor p) throws
IOException {
…
}
使用lambda表达式有个模式:环绕执行模式
第 1 步:行为参数化
第 2 步:使用函数式接口来传递行为
第 3 步:执行一个行为
第 4 步:传递 Lambda
这样是不是给力多了呢?
发现写个博客还出挺耗时间的?不知不觉夜已深了,洗洗睡了,但是精彩的lambda知识内容只是个开头啊,大家可以关注我,继续我们的lambda旅程。