Java 8之Lambda表达式实际应用

前面 Java 8之方法引用和Lambda表达式这篇文章讲了 方法引用Lambda表达式的大致原理和使用方法,但是光有理论是不够的,现在这篇文章会讲到它们的实际应用,从最开始的需求一步步的优化代码,直到最后使用Lambda表达式。

筛选苹果:

我们现在有个Apple类,它有weight和color属性分别代表它的重量和属性,我们创建多个苹果放入List中,这样就有了很多不同的苹果。

public class Apple {
    private String color;
    private Integer weight;

    public Apple(String color, Integer weight) {
        this.color = color;
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }
}

public static void main(String[] args) {
    List<Apple> apples = new ArrayList<Apple>();
    Apple apple1 = new Apple("red", 100);
    Apple apple2 = new Apple("green", 200);
    Apple apple3 = new Apple("red", 300);
    Apple apple4 = new Apple("red", 150);
    apples.add(apple1);
    apples.add(apple2);
    apples.add(apple3);
    apples.add(apple4);
}
  1. 假设我们现在有个Apple类,它有weight和color属性,现在有个需求,把红色的苹果挑出来,我们就写出了下列的代码。下面这段代码再常见不过了,把未分类的集合传进来,新建一个集合把筛选出来的元素放进去再返回,但是如果需求说要把绿色的都筛选出来呢?难道复制一个吗?那也太傻了,所以我们需要对代码进行改进。

    public static List<Apple> filterGreenApples(List<Apple> apples) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : apples) {
            if ("green".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }
  2. 经过我们的改进,把要筛选的颜色也当作参数传进来方法,这样想选什么样颜色就选什么颜色,但是需求永远都是会变得,如果说除了颜色还要再加上重量作为筛选呢?所以我们又对代码进行了改进。

    public static List<Apple> filterApplesByColor(List<Apple> apples, String color) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : apples) {
            if (apple.getColor().equals(color)) {
                result.add(apple);
            }
        }
        return result;
    }
    
  3. 既然要加多重量作为筛选条件,那干脆把重量也当作参数传进去,这个时候我们发现这段代码开始变得很恶心了,在项目很赶的时候很多人会写出类似这种代码,需求是实现了,但是几乎没有什么阅读性可言,而且最多过一个星期,连你自己都可能看不懂自己写的什么东西,而且如果代码没有BUG也就算了,有了隐藏BUG在中途被发现再改的话是越改越乱,所以肯定不能用这样的代码,我们得再改进代码。

    public static List<Apple> filterApples(List<Apple> apples, String color, int weight, boolean flag) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : apples) {
            if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) {
                result.add(apple);
            }
        }
        return result;
    }
    
  4. 现在封装方法的方式已经没办法很好的解决问题了,所以我们决定使用设计模式中的策略模式解决这个问题,我们新建一个接口,里面定义一个方法接受Apple参数,然后我们只要实现这个接口重写这个方法,就可以在这个方法里面自定义我们的筛选代码了,我们可以直接用匿名类省去创建类的步骤,这也是最常用的方法,比如新建线程传入Runnable接口就是这样的做法

    public interface ApplePredicate {
        boolean test(Apple apple);
    }
    
    public class AppleHeavyWeightPredicate implements ApplePredicate {
        public boolean test(Apple apple) {
            return apple.getWeight() > 150;
        }
    }
    
    public static List<Apple> filterApples(List<Apple> apples, ApplePredicate p) {
        List<Apple> result = new ArrayList<Apple>();
        for (Apple apple : apples) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }
    
    //使用匿名类
    List<Apple> redApples = filterApples(apples, new ApplePredicate() {
        public boolean test(Apple apple) {
            return "red".equals(apple.getColor());
        }
    });
    
  5. 到现在其实我们的代码已经优化的很好了,实际上Java 8以前很多类库也都是这样实现的,但是这样的做法也有它的问题,那就是一长串的模板代码,阅读性也不怎么好,所以现在要轮到我们的主角上场了,使用Lambda表达式来优化。

    List<Apple> result = filterApples(apples, (Apple apple) -> "red".equals(apple.getColor()));
    
  6. 到这里我们其实我们的目的已经实现了,但是我们还可以再改进代码,使这个方法不局限与Apple这个里,只需要加入泛型,就可以成为一个公用的筛选方法了,筛选任意的类型数据。我们把接口接受的参数类型改成泛型,返回的类型也改成泛型,接受的需要筛选的目标集合也改成泛型,这样就是一个可以筛选任何类型的公用方法了。

    public interface Predicate<T> {
        boolean test(T t);
    }
    
    public static <T> List<T> filter(List<T> list, Predicate<T> p) {
        List<T> result = new ArrayList<>();
        for (T e : list) {
            if (p.test(e)) {
                result.add(e);
            }
        }
        return result;
    }
    

Java自带类库使用Lambda表达式:

实际上Java 8中很多自带的类库已经可以使用Lambda表达式来调用了,就和我们上面的代码一样。

  1. 在Java 8中List自带了一个sort方法,接受Comparator(排序)类型参数,按照原来的方式就是是用匿名类,现在我们直接用Lambda表达式。

    public interface Comparator<T> {
        public int compare(T o1, T o2);
    }
    
    //匿名类使用方式
    apples.sort(new Comparator<Apple>() {
        public int compare(Apple a1, Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
        }
    });
    
    //Lambda表达式
    apples.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
    
  2. 同理线程也是可以这样进行改造

    public interface Runnable{
        public void run();
    }
    
    //匿名方法
    Thread t = new Thread(new Runnable() {
        public void run(){
            System.out.println("Hello world");
        }
    });
    
    //Lambda表达式
    Thread t = new Thread(() -> System.out.println("Hello world"));
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值