前言:
最近在系统性学习一些java8的新特性,说一下为什么打算系统的学习它呢。有下面几个原因:1、源码中经常有看到lambda表达式、Stream、Optional、LocalDate、LocalTime;2、从某书上看到java推荐函数式编程、并且新特性的内容性能提升了很多;3、装逼。如果你也对它感兴趣,那么从现在开始,咱们一起来学习吧,今天先将一下lambda表达式的入门、以及使用lambda表达式会给我们带来什么好处,我会从实际的例子出发,跟大家一起学习,绝对通俗易懂。
从需求入手,有一天我在睡午觉,农民伯伯找到我,让我帮他从一堆苹果中挑出绿色的苹果(苹果有颜色),我想这简单立马就搞定了,下面是我的实现的过程。
1、尝试一
代码语言:javascript复制public class Apple {
public Apple(String color, int weight) {
this.color = color;
this.weight = weight;
}
private String color;
private int 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;
}
}
这是Apple实体类的代码,超级简单的一个bean
代码语言:javascript复制private static List<Apple> filterGreenApple(List<Apple> inventory){
List<Apple> greenApples = new ArrayList<>();
//简单一点,就不对参数做空判断了
for(Apple apple : inventory){
if("green".equals(apple.getColor())){
greenApples.add(apple);
}
}
return greenApples;
}
上面是从一推苹果中选出颜色为绿色的苹果,是不是超级简单,而且没任何问题。那么现在农民伯伯的需求发生了改变,又需要我们从一堆苹果中挑出颜色为红色的苹果…
2、尝试二
这也很简单,只要将颜色变成参数就ok啦
代码语言:javascript复制private static List<Apple> findAppleByColor(List<Apple> inventory,String color){
//简单点,就不做参数校验了
List<Apple> colorApples = new ArrayList<>();
for (Apple apple : inventory){
if(color.equals(apple.getColor())){
colorApples.add(apple);
}
}
return colorApples;
}
非常简单,农民伯伯非常高兴,因为这样的话能挑选出任何颜色,只要将需要挑选的颜色传进去就行了。但是过了几天,农民伯伯又找到我,需要我帮忙从一堆苹果中挑选出比较大的苹果(苹果有重量,大于150g的认为是大苹果)
3、尝试三
同样很简单,几行代码就搞定了
代码语言:javascript复制private static List<Apple> findAppleByWeight(List<Apple> inventory,int weight){
List<Apple> weightApples = new ArrayList<>();
for (Apple apple : inventory){
if(apple.getWeight() > weight){
weightApples.add(apple);
}
}
return weightApples;
}
我把做好的内容给农民伯伯,农民伯伯很高兴的夸奖我正能干,但是过了几天农民伯伯来找到,我心中有了一丝不祥的预感,不会是又有啥需求吧,果不其然,这一次农名伯伯希望我能帮他挑选出的苹果又大又红,他说这种苹果的价格可以买的高点。
这个时候我陷入了沉思,我在想前面的设计是不是不太合体,非常的不灵活,这个时候我脑中思考是否能用到设计模式去解决类似的问题,23中设计模式在我的脑子里回想……突然想到了策略模式,定义一族算法,把它们封装起来,然后运行时选择一个算法,说干就干,这个时候代码变成下面的样子
4、尝试四
(1)抽象层
代码语言:javascript复制public interface ApplePredicate {
boolean test(Apple apple);
}
(2)具体的实现类
绿苹果筛选的策略
代码语言:javascript复制public class GreenApplePredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
if("green".equals(apple.getColor())){
return true;
}
return false;
}
}
大苹果筛选的策略
代码语言:javascript复制public class HeavyWeightApplePredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
if(apple.getWeight() > 150){
return true;
}
return false;
}
}
又大又红的苹果筛选的策略
代码语言:javascript复制public class RedAndHeavyApplePredicate implements ApplePredicate {
@Override
public boolean test(Apple apple) {
if ("red".equals(apple.getColor()) && apple.getWeight() > 150){
return true;
}
return false;
}
}
过滤苹果的方法
代码语言:javascript复制private static List<Apple> filterApple(List<Apple> inventory, ApplePredicate applePredicate){
List<Apple> filterApples = new ArrayList<>();
for (Apple apple : inventory){
if (applePredicate.test(apple)){
filterApples.add(apple);
}
}
return filterApples;
}
这个时候我微微一笑,心想,这次可以了,不管你用什么条件过滤我都能满足了,每次有新的过滤条件,我只要新增一个具体的实现类就行了,完全符合开闭原则。农名伯伯也非常的高兴….
接下来的半个月里,发生了下面的事情……
第一天:小洪童鞋,能不能帮俺挑选出青苹果…….
第二天:小洪童鞋,能不能帮俺挑选出重量在100-150g的苹果…
第三天:小红童鞋,我要筛选重量在200g以上的苹果……
……
这个时候,我同样发现了一个问题,我的类爆炸了,里面全部是ApplePredicate的实现的子类,我又在思考,如何能够解决问题呢?要不用匿名类试试?不用创建相应的实现类?
5、尝试五
代码语言:javascript复制List<Apple> redApples = filterApple(inventory, new ApplePredicate() {
@Override
public boolean test(Apple apple) {
if ("red".equals(apple.getColor())){
return true;
}
return false;
}
});
然后一顿操作猛如虎,一看战绩0-5,还是不优雅,匿名内部类太多了,代码不美观、阅读性也不好。正在我认真思考如何优化时,我的脑子里浮现出从哪段源码中看过如下类似的代码……
代码语言:javascript复制Thread thread = new Thread(()-> System.out.println("i am a thead ,i am running my name is " Thread.currentThread().getName()));
thread.start();
然后我开始翻阅资料,看看lambda表达式如何使用,最后我的代码做成了下面的修改,删掉了所有的ApplePredicate的具体实现类
代码语言:javascript复制List<Apple> redApples = filterApple(inventory,(Apple apple)-> "red".equals(apple.getColor()));
List<Apple> heavyApples = filterApple(inventory,(Apple apple)-> apple.getWeight() > 150);
List<Apple> redAndHeavyApples = filterApple(inventory,(Apple apple)->"red".equals(apple.getColor()) && apple.getWeight() > 150);
我看到了如此简短和优雅的代码,露出了满足的微笑,正在我准备休息的时候,农民伯伯打电话告诉我,他的橘子也快要出售了,让我按照苹果的方案,也给橘子做一套,他还说过两个月梨也要出售了,让我帮忙也弄一套,说改天请我吃烤全羊…….,我对着代码思考了一下,马上就搞定了,用个泛型就搞定啦
抽象层
代码语言:javascript复制public interface FruitsPredicate<T> {
boolean test(T fruits);
}
实现的过滤方法,这个时候不管是要过滤苹果、梨子、香蕉都ok啦
代码语言:javascript复制private static<T> List<T> filterFruits(List<T> inventory, FruitsPredicate<T> fruitsPredicate){
List<T> filterFruits = new ArrayList<>();
for (T t : inventory){
if (fruitsPredicate.test(t)){
filterFruits.add(t);
}
}
return filterFruits;
}
本篇文章就暂时先到这里了,希望这篇可以让小伙伴们发现lambda表达式的优势、以及如何帮我们解决哪些问题,今天先一起入个门,后面会更加深入的学习lambda表达式的使用。好了,终于搞定了,赶紧休息,不然又要掉几根头发了。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111220.html原文链接:https://javaforall.cn