Java8新特性学习之一:lambda表达式入门

2022-07-04 14:44:20 浏览数 (1)

前言:

最近在系统性学习一些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

0 人点赞