系统学习Java新特性-行为参数化

269 阅读3分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

阅读《Java实战》一书,系统学习梳理下Java8之后新增的特性,lambda表达式、方法引用、流、默认方法、Optional、CompletableFuture等等,本文为前两章的总结。

1、基础概念

1.1 流处理

  • Java8提供的Stream API,支持多个数据处理的并行操作,思路是从高层角度描述需求,而由“实现”(Stream库)来选择底层最佳执行机制。
  • 将集合的制造和处理构成抽象封装,如循环迭代直接由库内部进行,使用时不用纠结循环流程。
  • 提供封装的并行处理能力,基于分治+无共享可变状态。

1.2 方法引用&Lambda-匿名函数

  • 方法引用:类比对象引用,将方法作为一等值(执行时可做参数)来传递。

  • Lambda:将函数作为一等值来传递。

1.3 接口的默认方法

让接口支持声明默认的接口方法实现,只有类中没有实现具有默认方法的接口,才会去调用接口中的默认方法。

1.4 Java模块化

  • 解决问题:
    • 基于jar的java包没有声明的结构,不适合组件化构建。
    • 迭代演进中,一个接口的改变,实现该接口的所有类多要改变
  • 处理方式:
    • java9支持通过语法定义由一系列包组合成的模块,更好控制命名空间和包可见性。
    • 引入接口默认方法,支持接口持续演进,而不影响实现该接口的所有类。

1.5 其他内容

  • Optional处理null问题
  • 模式匹配

2、行为参数化演进

定义:

​ 一个方法可以接收多个不同的行为作为参数,并在内部使用他们,完成不同的行为能力。

演进场景:

​ 根据苹果的颜色或者重量属性遍历过滤出来苹果。

版本1:传统实现
    // 版本1: 直接迭代筛选
    public static List<Apple> filterApples(List<Apple> inventory,Color color){
        List<Apple> filterApples = new ArrayList<>();
        for(Apple apple:inventory){
            if(color.equals(apple.getColor())){
                filterApples.add(apple);
            }
        }
        return filterApples;
    }
版本2:基于行为接口+具体实现类,实现行为参数化
    // 版本2:基于接口+实现类的策略模式,用对象封装方法策略
    public static List<Apple> filterApples(List<Apple> inventory,ApplePredicate predicate){
        List<Apple> filterApples = new ArrayList<>();
        for(Apple apple:inventory){
            if(predicate.test(apple)){
                filterApples.add(apple);
            }
        }
        return filterApples;
    }
    // 行为接口
    interface ApplePredicate {
        public boolean test(Apple a);
    }
    // 行为参数化对象:红色苹果判断
    class AppleRedPredicate implements ApplePredicate{
        @Override
        public boolean test(Apple a) {
            return Color.RED.equals(a.getColor());
        }
    }
    // 行为参数化对象:红色苹果判断
    class AppleHeavyWeightPredicate implements ApplePredicate{
        @Override
        public boolean test(Apple a) {
            return a.getWeight()>150;
        }
    }
版本3:基于匿名类,简化类数量
// 版本3:基于匿名类
List<Apple> redApples3 = filterApples(inventory, new ApplePredicate() {
    @Override
    public boolean test(Apple a) {
        return Color.RED.equals(a.getColor());
    }
});
版本4:用lambda替换匿名类
// 版本4:用lambda简化匿名类
List<Apple> result = filterApples(inventory,(Apple a) -> Color.RED.equals(a.getColor()));
版本5:将List类型抽象化(将过滤行为复用)
    // 版本5:类型抽象化(引入类型参数)
    interface Predicate<T>{
        boolean test(T t);
    }
    // 泛化的过滤函数
    static <T> List<T> filter(List<T> list,Predicate<T> p){
        List<T> result = new ArrayList<T>();
        for(T e:list){
            if(p.test(e)){
                result.add(e);
            }
        }
        return result;
    }
	// 使用示例 
    List<Apple> result2 = filter(inventory,(Apple a) -> a.getWeight()>500);
    System.out.println(result2);
    // 过滤偶数
    Integer[] arrInt = {1,2,3,4,5,6};
    System.out.println(filter(Arrays.asList(arrInt),(Integer i) -> i%2==0));

完整示例代码

总结:

  • 核心:一个方法接受多个不同行为作为参数,并在内部使用它,完成不同能力。
  • 目的场景:适应不断变化的要求,不同行为参数化,减少硬编码,适合条件多变的排序&过滤的规则、线程等。
  • java8之前用匿名类来处理创建大量类实现问题,java8之后基于lambda实现