java8新特性(一):行为参数化

1、在Java8之前如果需要从一个苹果对象集合中选出绿色的苹果,通常是这么做的。

public static List<Apple> filterGreenApples(List<Apple> list){
    List<Apple> result =  new ArrayList<>();
    for(Apple apple: list){
        if( "green".equals(apple.getColor())){
            result.add(apple);
        }
    }
    return result;
}

2、 但是有经验的程序员不会像上面那么写,为了让程序更具有灵活性,会选择将颜色变成一个参数。

public static List<Apple> filterApplesByColor(List<Apple> list,  String color){
    List<Apple> result =  new ArrayList<>();
    for(Apple apple: list){
        if(color.equals(apple.getColor())){
            result.add(apple);
        }
    }
    return result;
}

这么做的好处就是这个方法可以应对需求的变更,可以用来过滤不同颜色的苹果,不仅仅是绿色的苹果。
除了根据颜色过滤之外,还可能需要根据其他属性过滤,比如重量,这时候你又会写一个方法来处理这个需求。

public static List<Apple> filterApplesByWeight(List<Apple> list,  int weight){
    List<Apple> result =  new ArrayList<>();
    for(Apple apple: list){
        if(apple.getWeight() > weight){
            result.add(apple);
        }
    }
    return result;
}

3、 这样做没什么问题,但是你复制了大部分代码,这违反了Don't Repeat Yourself的原则,所以我们需要更加优雅的解决办法。
我们先定义一个测试接口

public interface ApplePredicate {
    boolean test(Apple apple);
}

然后提供这个测试接口的实现类型

public class AppleHeavyWeightPredicate  implements ApplePredicate{
    @Override
    public boolean test(Apple apple) {
        return apple.getWeight() >  200;
    }
}

public class AppleGreenColorPredicate  implements ApplePredicate {
    @Override
    public boolean test(Apple apple) {
        return  "green".equals(apple.getColor());
    }
}


然后将这些测试接口的实现类型的实例作为一种策略传递给刷选苹果的方法, 这就是策略模式。

public static List<Apple> filterApples(List<Apple> list,  ApplePredicate predicate){
    List<Apple> result =  new ArrayList<>();
    for(Apple apple: list){
        if(predicate.test(apple)){
            result.add(apple);
        }
    }
    return result;
}

这样就实现了根据任一条件进行过滤的方法。


4、策略模式已经非常灵活可扩展,但是仍然有缺点, 就是冗余代码很多,需要 为每个策略预先定义一个实现类型 。解决这个问题可以使用匿名内部类。

List<Apple> redApples =  filterApples(appleList,  new ApplePredicate() {
    @Override
    public boolean test(Apple apple) {
        return  "red".equals(apple.getColor());
    }
});

5、匿名内部类 依然有很多冗余代码,  一个测试接口的实现类型实际上只有一行有效代码,所以需要不断优化。这个时候就轮到传说中的Lambda表达式 上场了。

List<Apple> redApples =  filterApples(appleList, (apple) ->  "red".equals(apple.getColor()));

一行代码解决问题, 这就是 Lambda表达式的威力。


6、对过滤方法进一步抽象, 使这个方法可以适用任何类型的集合的过滤。

public static < T> List< T> filterApples(List< T> list,  ApplePredicate< T> p){
    List< T> result =  new ArrayList<>();
    for( e: list){
        if(p.test(e)){
            result.add(e);
        }
    }
    return result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值