Lambda表达式

假设一个情景: 找出满足条件的Hero
从使用普通方法,匿名类,以及Lambda这几种方式,逐渐的引入Lambda的概念;
Hero类:

package org.example;
import java.util.Objects;

public class Hero {
    private String name;
    private float hp;
    private int damage;

    public Hero() {
    }

    public Hero(String name) {
        this.name = name;
    }

    public Hero(String name, float hp, int damage) {
        this.name = name;
        this.hp = hp;
        this.damage = damage;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getHp() {
        return hp;
    }

    public void setHp(float hp) {
        this.hp = hp;
    }

    public int getDamage() {
        return damage;
    }

    public void setDamage(int damage) {
        this.damage = damage;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                ", hp=" + hp +
                ", damage=" + damage +
                '}';
    }
}

普通方法

使用一个普通方法,在for循环遍历中进行条件判断,筛选出满足条件的数据

hp>100 && damage<50

具体代码:

public static void main( String[] args )
    {
        Random r = new Random();
        List heros = new ArrayList();
        for (int i = 0; i < 10; i++) {
            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
        }
        System.out.println("初始化后的集合:");
        System.out.println(heros);
        System.out.println("筛选出 hp>100 && damange<50的英雄");
        filter(heros);
    }
    private static void filter(List heros) {
        for (Hero hero : heros) {
            if(hero.getHp()>100 && hero.getDamage()<50)
                System.out.print(hero);
        }
    }

匿名类方式

首先准备一个接口HeroChecker,提供一个test2(Hero)方法,然后通过匿名类的方式,实现这个接口

package org.example.Anonymous;

import org.example.Hero;

public interface HeroCheck {
    public boolean test2(Hero h);
}

接着调用filter,传递这个checker进去进行判断,这种方式就很像通过Collections.sort在对一个Hero集合排序,需要传一个Comparator的匿名类对象进去一样。

package org.example.Anonymous;

import org.example.Hero;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Anonymous {
    public static void main( String[] args )
    {
        Random r = new Random();
        List heros = new ArrayList();
        for (int i = 0; i < 5; i++) {
            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
        }
        System.out.println("初始化后的集合:");
        System.out.println(heros);
        System.out.println("使用匿名类的方式,筛选出 hp>100 && damange<50的英雄");
        HeroCheck checker = new HeroCheck() {
            @Override
            public boolean test2(Hero h) {
                return (h.getHp()>100 && h.getDamage()<50);
            }
        };

        filter(heros,checker);
    }
    private static void filter(List heros,HeroCheck checker) {
        for (Hero hero : heros) {
            if(checker.test2(hero))
                System.out.print(hero);
        }
    }
}

Lambda方式

使用Lambda方式筛选出数据

filter(heros,(h)->h.hp>100 && h.damage<50);

同样是调用filter方法,从上一步的传递匿名类对象,变成了传递一个Lambda表达式进去

h->h.hp>100 && h.damage<50

咋一看Lambda表达式似乎不好理解,其实很简单,下一步讲解如何从上一个匿名类一点点演变成Lambda表达式

package org.example.Lamdba;

import org.example.Anonymous.HeroCheck;
import org.example.Hero;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Lamdba {
    public static void main( String[] args )
    {
        Random r = new Random();
        List heros = new ArrayList();
        for (int i = 0; i < 5; i++) {
            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
        }
        System.out.println("初始化后的集合:");
        System.out.println(heros);
        System.out.println("使用Lamdba的方式,筛选出 hp>100 && damange<50的英雄");

        filter(heros,hx->hx.getHp()>100 && hx.getDamage()<50);
    }
    private static void filter(List heros,HeroCheck checker) {
        for (Hero hero : heros) {
            if(checker.test2(hero))
                System.out.print(hero);
        }
    }
}

从匿名类演变成Lambda表达式

Lambda表达式可以看成是匿名类一点点演变过来

  1. 匿名类的正常写法
HeroChecker c1 = new HeroChecker() {
    public boolean test2(Hero h) {
        return (h.hp>100 && h.damage<50);
    }
};
  1. 把外面的壳子去掉
    只保留方法参数和方法体,参数和方法体之间加上符号 ->
HeroChecker c2 = (Hero h) ->{
    return h.hp>100 && h.damage<50;
};
  1. 把return和{}去掉
HeroChecker c3 = (Hero h) ->h.hp>100 && h.damage<50;
  1. 把 参数类型和圆括号去掉(只有一个参数的时候,才可以去掉圆括号)
HeroChecker c4 = h ->h.hp>100 && h.damage<50;
  1. 把c4作为参数传递进去
filter(heros,c4);
  1. 直接把表达式传递进去
filter(heros, h -> h.hp > 100 && h.damage < 50);
package lambda;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
 
import charactor.Hero;
 
public class TestLamdba {
    public static void main(String[] args) {
        Random r = new Random();
        List heros = new ArrayList();
        for (int i = 0; i < 5; i++) {
            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
        }
        System.out.println("初始化后的集合:");
        System.out.println(heros);
        System.out.println("使用匿名类的方式,筛选出 hp>100 && damange<50的英雄");
        // 匿名类的正常写法
        HeroCheck c1 = new HeroCheck() {
            @Override
            public boolean test2(Hero h) {
                return (h.hp > 100 && h.damage < 50);
            }
        };
        // 把new HeroChcekcer,方法名,方法返回类型信息去掉
        // 只保留方法参数和方法体
        // 参数和方法体之间加上符号 ->
        HeroCheck c2 = (Hero h) -> {
            return h.hp > 100 && h.damage < 50;
        };
 
        // 把return和{}去掉
        HeroCheck c3 = (Hero h) -> h.hp > 100 && h.damage < 50;
 
        // 把 参数类型和圆括号去掉
        HeroCheck c4 = h -> h.hp > 100 && h.damage < 50;
 
        // 把c4作为参数传递进去
        filter(heros, c4);
         
        // 直接把表达式传递进去
        filter(heros, h -> h.hp > 100 && h.damage < 50);
    }
 
    private static void filter(List heros, HeroCheck checker) {
        for (Hero hero : heros) {
            if (checker.test(hero))
                System.out.print(hero);
        }
    }
 
}

与匿名类概念相比较,Lambda 其实就是匿名方法,这是一种把方法作为参数进行传递的编程思想。
虽然代码是这么写

filter(heros, h -> h.hp > 100 && h.damage < 50);

但是,Java会在背后悄悄的把这些都还原成匿名类方式,引入Lambda表达式,会使得代码更加紧凑,而不是各种接口和匿名类到处飞。

Lambda的弊端

Lambda表达式虽然带来了代码的简洁,但是也有其局限性。

  1. 可读性差,与啰嗦的但是清晰的匿名类代码结构比较起来,Lambda表达式一旦变得比较长,就难以理解
  2. 不便于调试,很难在Lambda表达式中增加调试信息,比如日志
  3. 版本支持,Lambda表达式在JDK8版本中才开始支持,如果系统使用的是以前的版本,考虑系统的稳定性等原因,而不愿意升级,那么就无法使用。
  4. Lambda比较适合用在简短的业务代码中,并不适合用在复杂的系统中,会加大维护成本。

你可能感兴趣的:(Lambda表达式)