Java8--传递代码:一个例子

时间:2022-05-04 18:54:23
来看一个例子,看看它是如何帮助你写程序的。
java8源代码可以访问[https://github.com/java8/](https://github.com/java8/)

假设你有一个Apple类,它 有一个getColor方法,还有一个变量inventory
保存着一个Apples的列表。你可能想要选出所 有的绿苹果,并返回一个列表。
通常我们用筛选(filter)一词来表达这个概念。在Java 8之前, 你可能会写
这样一个方法filterGreenApples:

 public static List<Apple> filterGreenApples(List<Apple> inventory){     
           List<Apple> result = new ArrayList<>();     
           for (Apple apple: inventory){
                if ("green".equals(apple.getColor())) {
                        result.add(apple);
                }
           }
          return result; 
    } 
但是接下来,有人可能想要选出重的苹果,比如超过150克,于是你心情沉重地写了下面这 
个方法,甚至用了复制粘贴: 
 public static List<Apple> filterGreenApples(List<Apple> inventory){
           List<Apple> result = new ArrayList<>();
           for (Apple apple: inventory){
                if (apple.getWeight() > 150) {
                     result.add(apple);
                }
           }     
           return result; 
    } 

我们都知道软件工程中复制粘贴的危险——给一个做了更新和修正,却忘了另一个。嘿,这 两个方法只有一行不同:if里面高亮的那行条件。如果这两个高亮的方法之间的差异仅仅是接受 的重量范围不同,那么你只要把接受的重量上下限作为参数传递给filter就行了,比如指定 (150, 1000)来选出重的苹果(超过150克),或者指定(0, 80)来选出轻的苹果(低于80克)。
但是,我们前面提过了,Java 8会把条件代码作为参数传递进去,这样可以避免filter方法 出现重复的代码。现在你可以写:

    public static boolean isGreenApple(Apple apple) {
           return "green".equals(apple.getColor()); 

    public static boolean isHeavyApple(Apple apple) {     
           return apple.getWeight() > 150; 
    } 

    public interface Predicate<T>{  
           boolean test(T t); 
    } 

    static List<Apple> filterApples(List<Apple> inventory,Predicate<Apple> p) {    
           List<Apple> result = new ArrayList<>();                                  
           for (Apple apple: inventory){
               if (p.test(apple)) {
                   result.add(apple);
               }
           }
           return result; 
    } 

    要用它的话,你可以写: 
        filterApples(inventory, Apple::isGreenApple);
    或者 
        filterApples(inventory, Apple::isHeavyApple); 
现在重要的是你可以在Java 8里面传递 方法了!