《软件架构基础》函数式编程

编程

特点

  • 函数作为一等公民

$("button").click(function(){

$("li").each(function(){

alert($(this).text())

});

});

  • 无副作用

    • 函数的副作用指的是函数在调用过程中,除了给出了返回值外,还修改了函数外部的状态,比如,函数在调用过程中,修改了某一个全局状态。函数式编程认为,函数的副用作应该被尽量避免。
    • 函数做了除了约定之外的其它事情

  • 引用透明

    • 引用透明(Referential transparency),指的是函数的运行不依赖于外部变量或“状态”,只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

  • 申明式的(Declarative)

    • 相对于命令式(imperative)而言,命令式的程序设计喜欢大量使用可变对象和指令

    • 申明式的编程:申明你的用意

      public static void imperative(){ 

      int[] iArr={1,3,4,5,6,9,8,7,4,2};

      for(int i=0;i<iArr.length;i++){

      System.out.println(iArr[i]);

      }

      }

      public static void declarative(){

      int[] iArr={1,3,4,5,6,9,8,7,4,2};

      Arrays.stream(iArr).forEach(System.out::println);

      }

  • 不变模式

    static int[] arr={1,3,4,5,6,7,8,9,10};

    Arrays.stream(arr).map((x)->x=x+1).forEach(System.out::println);

    System.out.println();

    Arrays.stream(arr).forEach(System.out::println);

  • 易于并行

    • 不变模式天生是并行的
    • 引用透明

  • 更少的代码

    • 属于“结构化编程”的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用
    • 如 (1 + 2) * 3 - 4

    subtract(multiply(add(1,2), 3), 4)

    • 变形后

    add(1,2).multiply(3).subtract(4)

  • 易于阅读的

为什么使用

  • 易于并行
  • 易于进行数据处理
  • 更好的模块化
  • 高效的(可工作的软件 重于 详尽的文档)
  • 回归简单

java8

  • @FunctionalInterfacce

  • lambda表达式

    • lambda表达式即匿名函数,它是一段没有函数名的函数体
    • 可以作为参数
    • lambda中访问外部变量视为final

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);  

    numbers.forEach((Integer value) -> System.out.println(value));

    final int num = 2;

    Function<Integer, Integer> stringConverter = (from) -> from * num;

    System.out.println(stringConverter.apply(3));

  • 方法引用

    • 静态方法引用:ClassName::methodName
    • 实例上的实例方法引用:instanceReference::methodName
    • 超类上的实例方法引用:super::methodName
    • 类型上的实例方法引用:ClassName::methodName
    • 构造方法引用:Class::new
    • 数组构造方法引用:TypeName[]::new

java8函数式编程基础

  • Stream 一组待处理的数据
  • Predicate 谓词 ,返回是或不是
  • Function 将一个对象映射成另一个元素
  • BiFunction 将两个对象映射成一个对象
  • Consumer 消费者, 放在终结操作,即最后对元素做什么
  • BiConsumer消费两个对象,,产生某种行为
  • Supplier有返回值的Runable

基于Stream的操作

  • forEach
  • filter
  • map
  • reduce
  • collect
  • peek

操作分类

  • 中间函数与惰性求值

    • 中间函数返回一个流,程序中可以多次地、串接地调用流的操作,因为中间操作如映射map、过滤filter函数返回一个流对象。这类操作具有惰性。虽然代码写出了对它们 的调用,但是并没有真正执行。

  • 结尾函数

    • 结尾函数返回一个值或void函数产生一个副作用/side effect。

foreach

  • 结尾函数

    Arrays.stream(new int[]{1,2,3,5}).forEach(x->System.out.println(x));

filter

  • 接收一个谓词操作,如果谓词返回true,那么当前元素就会被处理,如果谓词返回false,那么元素就会被简单的丢弃

    static int[] arr={1,3,4,5,6,7,8,9,10};

    public static void main(String[] args) {

    Arrays.stream(arr).filter((x)->x%2==0).forEach(System.out::println);

    }

map

  • 对元素进行映射

    static int[] arr={1,3,4,5,6,7,8,9,10};

    public static void main(String[] args) {

    Arrays.stream(arr).map((x)->x*x).forEach(System.out::println);

    }

reduce

  • 对元素进行汇聚

    collect

  • 将元素转为集合

peek

  • 监视,调试

Optional

  • 一个用于处理NULL的对象
  • 用于传递可能为NULL的意图
  • 避免NULL打断程序流,使程序流更顺创

Optional的核心API-1

  • public boolean isPresent()

    • 判断当前值是否存在。相当于null检查。

  • public void ifPresent(Consumer<? super T> consumer)

    • 相对于进行null的判断,如果值有意义,则进行consumer操作。

  • public static <T> Optional<T> of(T value)

    • 这是一个工厂方法,构造一个包装了value的Optional。

  • public static <T> Optional<T> ofNullable(T value)

    • 工厂方法,如果value为null,则返回empty对象。否则等同于of()函数。

Optional的核心API-2

  • public T get()

    • 返回Optional内的包装对象。如果为null,则抛出一个异常。

  • public Optional<T> filter(Predicate<? super T> predicate)

    • 判断当前值是否满足predicate条件。如果不满足,则返回一个empty。

  • public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

    • 通过mapper,对当前的值做一个转换。

  • public T orElse(T other)

    • 如果当前值为空,则给一个默认的other作为值。

  • public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

    • 如果值为空,则抛出一个异常。

  • stus.stream()

    .forEach(

    (x)->Arrays.stream(x.getScores())

    .average()

    .ifPresent(System.out::println)

    );

Optional经验分享

  • 尽量不要直接使用get(),isPresent()方法
  • 尽量依赖map() orElse() 等等
  • Optional和异常不兼容

数据流上统计操作

  • IntStream对数据流提供了便捷的统计操作

  • average()

  • count()

  • sum()

  • max()

    static Comparator<Student> aveScore=(u1,u2)->ave(u1)>ave(u2)?1:-1;

    public static double ave(Student stu){

    return Arrays.stream(stu.getScores()).average().orElse(0);

    }

    public static void main(String[] args) {

    //取得平均分最高的同学

    stus.stream().max(aveScore).ifPresent(System.out::println);

    }

  • min()

Collector接口

对流中的元素进行收集和汇聚操作

元素收集到一个集合中

字符串拼接

统计计算 max min sum

  • 创建结果容器
  • 将新元素加入容器
  • 合并两个容器
  • 执行最终转换操作得到结果(可选)

以上是 《软件架构基础》函数式编程 的全部内容, 来源链接: utcz.com/z/513089.html

回到顶部