Java 8之Lambda表达式实际应用

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

筛选苹果:

咱们如今有个Apple类,它有weight和color属性分别表明它的重量和属性,咱们建立多个苹果放入List中,这样就有了不少不一样的苹果。segmentfault

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. 通过咱们的改进,把要筛选的颜色也看成参数传进来方法,这样想选什么样颜色就选什么颜色,可是需求永远都是会变得,若是说除了颜色还要再加上重量做为筛选呢?因此咱们又对代码进行了改进。app

    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在中途被发现再改的话是越改越乱,因此确定不能用这样的代码,咱们得再改进代码。ide

    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表达式来优化。this

    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表达式。code

    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"));
相关文章
相关标签/搜索