函数式编程及Lamda

作者: liaowenhao | 来源:发表于2017-09-03 20:43 被阅读94次

    函数式编程

    定义

    函数式编程(funcational programming)属于结构化编程的一种。主要思想是把运算过程尽量写成一系列嵌套的函数调用。

    结构化编程
    一种编程范型,采用子程序、代码区块、for循环以及while循环 等结构来取代传统的goto

    函数式编程关心数据的映射,命令式编程关心解决问题的步骤。

    特点
    1. 函数是“第一等公民”
      函数和其他数据类型一样,可以赋值给其他变量,作为其他函数的传入参数或返回值。

    2. 只用“表达式”,不用“语句”
      “expression” 是一个单纯的运算过程,总是有返回值。“statement”是执行某种操作,没有返回值。

    3. 没有“副作用”
      “副作用”是指函数内部有与外部的互动,产生运算以外的其他结果。函数要保持独立,所有功能返回一个新的值,尤其不得修改外部变量的值。

    纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

    1. 不修改状态
      函数式编程使用参数保存状态,只返回新的值,不修改系统变量。

    2. 引用透明(Referential transparency)
      函数的运行不依赖外部变量或“状态”,只依赖输入参数。只要参数相同,引用函数返回值总是相同的。

    构成
    • 高阶函数(higher-order function)
      能够接受一个函数作为参数的函数。

    • 函子(Functor)
      函子是函数式编程里最重要的数据类型,也是基本的运算单位和功能单位。
      函子是指具有map方法的容器,包含了值和变形关系。map方法将容器里面的每一个值,映射到另一个容器。即将一个范畴转换成令一个范畴。

    构成范畴这种数据模型的要素:
    所有成员是一个集合
    变形关系是函数

    • 闭包(Closure)
      闭包就是能够读取其他函数内部变量的函数,可简单理解成"定义在一个函数内部的函数"。当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。
      类是有行为的数据,闭包是有数据的行为。
      闭包是由函数及其相关的引用环境组合而成的实体,即闭包=函数+引用环境
    参考

    函数式编程入门教程
    函数式编程初探
    学习Javascript闭包(Closure)

    lambda

    lambda表达式通常在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。参考

    Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。

    JAVA中的lambda

    Java8之前,传递行为的唯一方法就是通过匿名内部类。Java中的lamda不是一个匿名内部类的语法糖。在匿名类中,this指代的是匿名类本身;而在lambda表达式中,this指代的是lambda表达式所在的这个类。

    1.lambda表达式
    只有那些仅仅包含一个非实例化抽象方法的接口才能使用lambda表达式。Runnable接口就是函数式接口的一个例子。

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    

    Java8默认带有许多可以直接在代码中使用的函数式接口,它们位于java.util.function包中。

    2.lambda表达式结构
    -> 是用来把参数从函数体中分离出来的操作符。
    在lambda表达式中,我们不需要明确指出参数类型,javac编译器会通过上下文自动推断参数的类型信息。根据上下文推断类型的行为称为类型推断

    3.方法引用
    当需要为一个特定方法创建lambda表达式,比如Function<String, Integer> strToLength = String::length;,可以用缩写符号表示。String是目标引用,::是定界符,length是目标引用的方法。该方法可以是静态或者实例方法。
    参考原文

    4.实现机制
    采用在Java7中新增的动态启用来延迟在运行时的加载策略。当javac编译代码时,捕获代码中的lambda表达式并生成一个动态启用的调用地址(称lambda工厂)。当动态启用被调用时,就会向lambda表达式发生转换的地方返回一个函数式接口的实例。

    JAVA中的Stream

    Stream是Java 8 提供的高效操作集合类(Collection)数据的API。Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对JAVA集合运算和表达的高阶抽象。

    1. Collection对比
      Java8运行开发者使用stream方法基于Collection集合创建一个Stream管道。Stream采用内部迭代。
      CollectionStream处理集合方式的不同:

      Collection与Stream处理集合方式的不同
    2. 懒加载
      Stream不会储存数据,懒加载(只有在被使用到时才会执行计算)。Stream表达式在被末端操作方法调用之前不会被赋值计算。

    • 过渡操作:从已存在的stream上产生另一个新的stream的函数,比如filter,map,sorted
    • 末端操作:从stream上产生一个非stream结果的函数,比如collect(toList()),forEach,count,get

    参考原文

    感想

    在一棵树上吊死是大多数非理性死忠的表现。

    相关文章

      网友评论

        本文标题:函数式编程及Lamda

        本文链接:https://www.haomeiwen.com/subject/gnwjjxtx.html