为什么要用Lambda表达式?(详细实例解释)

        在Java 8中,新增了Lambda表达式功能。那么,Lambda表达式能帮助我们干什么呢?

        下面我将用一个真实的例子一步步证明Lambda表达式将会给我们的Coding体验带来非凡的提升。

使用场景如下:

        现在,农民伯伯给我们提了一个新的需求,他们希望我们可以开发一个组件,帮助农民伯伯从数量不等的苹果中过滤出绿色的苹果。

为了完成这个需求,需要做如下设计

Version 1:

(1)编写一个苹果的实体类,主要包含三个属性:颜色,重量,品种。

package org.example.lamdba;

import java.util.Arrays;

import java.util.List;

public class Apple {

private String color;

private int weight;

private String variety;

/**

    * 空构造函数

    */

    public Apple(){

}

/**

    * 完全构造函数

    * @param color

    * @param weight

    * @param variety

    */

public Apple(String color,int weight,String variety){

this.color = color;this.weight = weight;this.variety = variety;}

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 String getVariety() {return variety}

public void setVariety(String variety) {this.variety = variety;}

public static List sampleList(){

return Arrays.asList(

new Apple("红色",150,"红富士"),new Apple("红色",149,"红富士"),new Apple("绿色",135,"青苹果"),new Apple("绿色",136,"青苹果"),

new Apple("红色",155,"红富士"),new Apple("深红色",145,"红元帅"),new Apple("深红色",142,"红元帅")

);}}

(2): 编写一个Demo类,类名LambdaDemoV1,该Demo类中含有根据颜色过滤的三个方法,并且有可以直接运行的main方法(抱歉,本人不喜欢用Junit的test,哈哈)

package org.example.lamdba;

import java.util.ArrayList;

import java.util.List;

public class LambdaDemoV1 {

public static void main(String[] args) {

List apples = Apple.sampleList();

List blueApples =filterGreenApples(apples);

List redApples =filterRedApples(apples);

List crimsonApples =filterCrimsonApples(apples);

}

//筛选绿苹果

    public static List filterGreenApples(List inventory){

List result =new ArrayList<>();

for(Apple apple:inventory){

if("绿色".equals(apple.getColor())){

result.add(apple);}}

return result;

}

//筛选红苹果

    public static List filterRedApples(List inventory){

List result =new ArrayList<>();

for(Apple apple:inventory){

if("红色".equals(apple.getColor())){

result.add(apple);}}

return result;

}

//筛选深红苹果

 public static List filterCrimsonApples(List inventory){

List result =new ArrayList<>();

for(Apple apple:inventory){

if("深红色".equals(apple.getColor())){

result.add(apple);}}

return result;}}

        通过Version 1 版本的设计,我们已经基本完成了农民伯伯的要求,但是,作为开发者,我们需要对上述的通过苹果颜色筛选苹果的方法做一次整合,将颜色作为一个参数,防止添加一个颜色筛选功能就新添加一个方法。

Version 2 :

Coding如下:

//根据苹果的颜色筛选苹果 重新设计filterGreenApples,filterRedApples,filterCrimsonApples方法 =>filterColorApples方法

public static List filterColorApples(List inventory,String color){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(color.equals(apple.getColor())){

result.add(apple);}}

return result;}


         经过Version 2 版本的整合,农民伯伯已经可以方便的使用我们提供的工具筛选特定颜色的苹果。但是,现在农民伯伯又提出了一个新的需求,他希望我们可以向他提供一个筛选特定重量苹果的新功能,(农名伯伯将单个苹果的质量超过150g的成为重苹果,小于等于150g的称为轻苹果)

Version 3 Coding: 如下

public class LambdaDemoV3 {

public static void main(String[] args) {

List apples = Apple.sampleList();

List blueApples =filterColorApples(apples,"绿色");

List redApples =filterColorApples(apples,"红色");

List crimsonApples =filterColorApples(apples,"深红色");

List heavyApples =filterApplesByWeight(apples,150);

}

//根据苹果的颜色筛选苹果

public static List filterColorApples(List inventory,String color){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(color.equals(apple.getColor())){

result.add(apple);}}

return result;}

//根据苹果的重量筛选苹果

public static List filterApplesByWeight(List inventory,int weight){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(apple.getWeight() > weight){

result.add(apple);}}

return result;}}

        在上面的版本中,新增功能方法filterApplesByWeight,农民伯伯可以通过将weight参数设置成150g方便的筛选出重量150g的苹果集。但是,这时,作为开发者,我们想到了这样一个问题,现在,农民伯伯只提出了通过颜色或者重量属性筛选苹果,要是接下来,农民伯伯希望通过产地,大小等苹果的其它属性进行筛选,怎么办,难道我们要一直增加新的方法吗?当然不是,通过观察学习现有的代码,我们发现其实真正因为功能变化而发生变化的代码只有 if(color.equals(apple.getColor())) => if(apple.getWeight() > weight),其它的都是样板代码(即处理流程)。我们是否可以换一个角度去思考解决这个问题呢?当然有,为此我们提出了一个新的解决方案,即 行为参数化。

Version 4

coding如下:


public interface ApplePredicate {

boolean test (Apple apple);}


public class AppleGreenColorPredicateimplements ApplePredicate{

@Override

    public boolean test(Apple apple) {

return "绿色".equals(apple.getColor());}}

public class AppleHeavyWeightPredicateimplements ApplePredicate{

@Override

public boolean test(Apple apple) {

return apple.getWeight() >150;}}


public class LambdaDemoV4 {

public static void main(String[] args) {

List apples = Apple.sampleList();

List heavyApples =filterApples(apples,new AppleGreenColorPredicate());

List greenApples =filterApples(apples,new AppleHeavyWeightPredicate());

}

public static List filterApples(List inventory,ApplePredicate p){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(p.test(apple)){

result.add(apple);}}

return result;}}

        在这个版本的Coding中,我们进行了建模,即创建了含有单个函数的接口ApplePredicate。该函数约定返回一个boolean值,而其具体实现需要使用者去创建。之后在改进版的filterApples方法中,将ApplePredicate p 传入参数。这样农民伯伯通过创建ApplePredicate的不同实现就可以使用filterApples提供的颜色,重量,品种等的不同筛选功能。

        从开发者的角度考虑,功能组件已经满足了农民伯伯的常用需求,api简单,易用。且开发者以极小的成本代价完成了丰富的功能需求。但是,通过观察代码,我们发现,农民伯伯在使用我们的filterApples时必须先创建实现一个ApplePredicate的子类,再应用filterApples方法。功能的确实现了,但是存在将代码的繁琐由开发者向使用者转嫁的嫌疑。

         通过分析,我们决定使用 匿名类的 方式对上述代码做一次优化。

Version 5:


public class LambdaDemoV5 {

public static void main(String[] args) {

List apples = Apple.sampleList();

List heavyApples =filterApples(apples,new ApplePredicate(){

@Override

public boolean test(Apple apple) {

return apple.getWeight() >150;}});

List greenApples =filterApples(apples,new ApplePredicate(){

@Override

public boolean test(Apple apple) {

return "绿色".equals(apple.getColor());}});}


public static List filterApples(List inventory,ApplePredicate p){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(p.test(apple)){

result.add(apple);}}

return result;}}

上述代码中使用了Java 匿名类的方式减少了代码量,但是依旧有些繁琐,接下来,我们可以使用最后一个大招,Lamdba表达式

Version 6:

public class LambdaDemoV6 {

public static void main(String[] args) {

List apples = Apple.sampleList();

List heavyApples =filterApples(apples,(Apple apple) ->apple.getWeight() >150);

List greenApples =filterApples(apples,(Apple apple) ->"绿色".equals(apple.getColor()));

}

public static List filterApples(List inventory,ApplePredicate p){

List result =new ArrayList<>();

for(Apple apple:inventory){

if(p.test(apple)){

result.add(apple);}}

return result;}}

        查看上述代码,是不是足够骚浪贱。Java允许我们使用Lambda表达式替代传统的匿名类创建使用方式,当该参数接口是含有单个函数的函数式接口,我们就可以使用Lambda表达式去替代匿名类的使用方式。这就是Lambda的强大之处。极大缩短代码行数,同时大大提高代码的易读性。这时,我们去回看Version 1的代码,当时LambdaDemoV1实现的功能仅有筛选颜色,而且开发了不同的三个方法才完成,转到Version 6的代码,LambdaDemoV6的filterApples方法 可以满足 使用者对苹果的重量,颜色,品种等不同属性的过滤筛选,功能大大增强,同时,使用方面,仅需要农民伯伯编写 List heavyApples =filterApples(apples,(Apple apple) ->apple.getWeight() >150);简短的代码就可以使用了,嗨到爆!

完成这篇博客我花费了将近一天的时间,如果有错误的地方,请及时联系我,谢谢!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348