Lambda表达式再思考

陌路散爱 提交于 2020-01-19 15:15:34



原因

之前写过一篇关于Lambda表达式的文章 ,最近又回头看了看,觉得不太满意,从新思考了一下,再写篇新的。

本文参考《Java8实战》 ,作者:[英] Raoul-Gabriel Urma [意] Mario Fusco [英] Alan Mycroft

一、不断变化的需求

第一天:产品经理来找你,说:“我这里有一堆苹果,我要把绿的拿出来”
好了,于是我写了下边的代码:

苹果类:


import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Apple {
    private String color;
    private long weight;
}

获取绿色苹果:

  public static List<Apple> findGreenApple(List<Apple> apples){
        List<Apple> list = new ArrayList<>();
        for (Apple apples1 : apples){
            if (apples1.getColor().equals("green")){
                list.add(apples1);
            }
        }
        return list;
    }

测试类:

public static void main(String[] args){
        List<Apple> list= Arrays.asList(new Apple("green",1L ),new Apple("red",2L),new Apple("red",1L),new Apple("yellow",3L));
        List<Apple> greenApple = findGreenApple(list);
        System.out.println(greenApple);
    }

结果:
在这里插入图片描述

第二天:产品经理说:“我不要绿苹果了,我要红苹果,你给我改成把红苹果拿出来”
好,改。

public static List<Apple> findRedApple(List<Apple> apples){
        List<Apple> list = new ArrayList<>();
        for (Apple apples1 : apples){
            if (apples1.getColor().equals("red")){
                list.add(apples1);
            }
        }
        return list;
    }

green->red不就可以了嘛!

第三天:产品经理说,“我不要按颜色取了,你把重量1斤以上的苹果都给我取出来!”
好,再改。

public static List<Apple> findAppleByWeight(List<Apple> apples){
        List<Apple> list = new ArrayList<>();
        for (Apple apples1 : apples){
            if (apples1.getWeight()>1){
                list.add(apples1);
            }
        }
        return list;
    }

第四天:产品经理说,“再改改,你把重量1斤以上的红苹果都给我取出来!”

你就说,你想不想揍他。

这时候怎么办?还改代码?

以后产品经理可能还会告诉你,“把X斤以上绿苹果取出来”

当我们频繁的改动代码,或程序中出现了大量的重复代码时,作为owner,我们需要警觉了。


二、有什么处理方式才能应对这种不断变化的需求呢?

我们可以用策略模式
但是像这种绿苹果、红苹果、红绿苹果等等,每加个需求就加个策略,难免出现很多重复的代码。

这时候我们可以考虑 Lambda表达式


三、 Lambda表达式

Java8以后支持行为参数化,即可以在参数中传递方法(个人理解)。

首先,我新建一个泛型接口,接口中方法test返回值为boolean类型,参数为任意类型。

@FunctionalInterface
public interface AppleTest<T> {
    boolean test(T t);
}

然后,在getAppleByCorlorOrWeight方法中把接口传进去

//一个参数返回Boolean
    public static List<Apple> getAppleByCorlorOrWeight(List<Apple> apples , AppleTest<Apple> p){
        List<Apple> result = new LinkedList<>();
        for (Apple apple :apples){
            if (p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

最后,运用lambda,我可以任意获得任何颜色或者重量的苹果。

public static void main(String[] args){
        List<Apple> list= Arrays.asList(new Apple("green",1L ),new Apple("red",2L),new Apple("red",1L),new Apple("yellow",3L));
    
       System.out.println(getAppleByCorlorOrWeight(list,apple -> apple.getColor().equals("red")));
       System.out.println(getAppleByCorlorOrWeight(list,apple -> apple.getWeight() > 1L));
    }

在这里插入图片描述

那么,我要获得某颜色某重量的苹果怎么办呢?


四、函数式接口

新建接口BiAppleTest,允许抽象方法传递两个参数

@FunctionalInterface
public interface BiAppleTest<T,U> {
    boolean test(T t, U u);
}

新建getAppleByCorlorAndWeight方法调用

    //两个参数返回Boolean
    public static List<Apple> getAppleByCorlorAndWeight(List<Apple> apples,BiAppleTest<String,Long> p){
        List<Apple> result = new LinkedList<>();
        for (Apple apple:apples){
            if (p.test(apple.getColor(), apple.getWeight())){
                result.add(apple);
            }
        }
        return result;
    }

测试:

 public static void main(String[] args){
        List<Apple> list= Arrays.asList(new Apple("green",1L ),new Apple("red",2L),new Apple("red",1L),new Apple("yellow",3L));
   
       System.out.println(getAppleByCorlorAndWeight(list,(c,w)->c.equals("red") && w>1L));
      
    }

结果:
在这里插入图片描述

那么问题又来了,我要获取符合某些条件的苹果,建立了两个函数式接口AppleTest、BiAppleTest,那如果我以后找符合某些条件的梨、香蕉、香蕉梨…难道都要去建立相应的函数式接口吗?

当然不用!Java8为我们提供了四大函数式接口,我建立的AppleTest、BiAppleTest分别对应着java8提供的Predicate、BiPredicate,以上代码可以换成:

 //一个参数返回Boolean
    public static List<Apple> getAppleByCorlorOrWeight(List<Apple> apples , Predicate<Apple> p){
        List<Apple> result = new LinkedList<>();
        for (Apple apple :apples){
            if (p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

    //两个参数返回Boolean
    public static List<Apple> getAppleByCorlorAndWeight(List<Apple> apples, BiPredicate<String,Long> p){
        List<Apple> result = new LinkedList<>();
        for (Apple apple:apples){
            if (p.test(apple.getColor(), apple.getWeight())){
                result.add(apple);
            }
        }
        return result;
    }

AppleTest、BiAppleTest并不需要自己去建立。
java8还为我们提供了很多函数式接口,都在rt.jar里,有兴趣的可以玩一玩。
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!