[Java] 函数式编程相关概念 - 笔记2

匿名函数 ( Anonymous function )

1. 匿名函数,是指没有被绑定到标识符的函数。根据字面意思,也可以理解为没有名字的函数。

2. 匿名函数通常:

  1). 作为参数,被传递给高阶函数。

  2). 作为高阶函数的返回值。

3. 在函数式编程语言,以及其他拥有头等函数的语言中,匿名函数比较普遍。

4. 在一些编程语言中,匿名函数被关键字 lambda 所标记。所以,匿名函数有也被称为Lambda 表达式 ( Lambda express )。例如,Python 就使用 lambda 进行标记

def h(x):
    return lambda y: x + y

5. 匿名函数是嵌套函数的一种,可以访问外层函数的变量,即其非局部变量。这也意味着,匿名函数需要实现闭包

6. 匿名函数是一种编程风格。匿名函数从来都不会是解决问题的唯一方式。每一个匿名函数都可以重新定义为有名的函数,并调用该有名函数。

7. 匿名函数除了用于上面提到的高级函数,闭包之外,也常用于柯里化场景。

高阶函数( Higher-order function )

1. 一个函数被称为高阶函数,需要满足至少一个条件

  1). 定义一个或多个函数作为自身的参数

  2). 返回一个函数作为自身的返回值。

2. 上面 python 例子 h(x) 便是一个高阶函数。C 语言的标准函数 qsort 也是高阶函数。

map

1. map 是一个常见的高阶函数,将给定数据集合的每一个元素,传入给定函数中并进行调用,并返回被调用后的数据集合,元素次序不变。常被称为“apply-to-all”,即全部调用。

2. 下面是一个求平方的 map 应用,用 scheme 来实现。

先定义求平方算法

square x = x * x

然后调用 map

>>> map square [1, 2, 3, 4, 5]

产生的结果为 [1, 4, 9, 16, 25]。

在 Java 8 中,引入了 stream.map(func) 来支持 map 功能。代码如下

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> squreList = numbers.stream().map(i -> i*i).collect(Collectors.toList());

        System.out.println(numbers);    // output : [1, 2, 3, 4, 5]
        System.out.println(squreList);   // output : [1, 4, 9, 16, 25]

柯里化 ( Currying )

1. 柯里化是一种函数转换技术,将一个多参数的函数,转换为一些列只需要单个参数的函数,其中这一系列的函数单参数和之前的多参数一一对应。

function divide(x, y){
    return x / y
}

function divior(d){
    return function(x){
        return divide( x, d);
    }
}

var half = divior(2)
var third = divior(3)

half(24)    // return 12
third(24)   // return 8

2. 在数学分析中,有一些分析技术只支持单参数函数,但是实用的函数通常定义多个参数。柯里化就是将多参数函数转化为一些系列的单参数函数。这个技术多用于理论分析,较少应用于工业生产。

头等函数 ( First-class function )

1. 一个编程语言支持头等函数,即意味着把函数作为一等公民,或者说是一等类型。拥有下面几个特性

  1). 可以把函数作为参数传递给其他函数

  2). 可以把函数作为其他函数的返回值

  3). 可以把函数赋值给变量,或者存储到数据结构中。

2. 函数的标示符,就是一个普通的变量,类型为函数类型,没有其他特别状态。

3. 头等函数是函数式编程风格的前提条件,因为函数式编程把高阶函数作为常用的方式。

4. 一个函数可以成为一个变量的值,那么就要判断两个函数是否相等。主要有两种相等。

  1). 内涵相等( Intensional equality )。通过对比函数体的源代码,来判断两个函数是否相等。

  2). 引用相等( Reference equality )。所有的函数都有一个对应的标识符,通过判断两个函数的标识符是否相等来决定函数本身是否相等。所以,两个分别定义的方法,即使他们的源代码一抹一眼,也会被认为是不相等。大多数语言使用引用相等的方式来判断函数间是否相等。

5. Javascript 基本完整地支持头等函数。

Java 8 引入的闭包,仅仅能获取到不变的非局部变量。Java 里面还没有函数类型。

参考资料

Anonymous function, wikipedia

Higher-order function, wikipedia

Map (higher-order function), wikipedia

Curring, wikipedia

First-class function, wikipedia

时间: 2024-11-03 22:55:13

[Java] 函数式编程相关概念 - 笔记2的相关文章

[Java] 函数式编程相关概念 - 笔记1

Java 8 引入了 lambda 表达式,以及函数式编程风格.在了解函数式编程过程中,做了些笔记,摘录于本文. 嵌套函数( Nested Function ) 1. 嵌套函数,是指在另一个函数里面定义的一个函数.外层的函数,这里简称为外层函数. 2. 函数的嵌套可以是多层嵌套.嵌套函数可以看到其全部的外层函数的非局部变量.在实际程序中,嵌套的层数一般很少.下面是一个三层嵌套的例子, innerOfInner 也可以访问在 outer 函数体重定义的变量 x . function outer()

JAVA GUI编程学习笔记目录

1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之GUI编程窗体事件 6.JAVA之GUI编程Action事件 7.JAVA之GUI编程鼠标事件 8.JAVA之GUI编程键盘码查询器 9.JAVA之GUI编程列出指定目录内容 10.JAVA之GUI编程弹出对话框Dialog 11.JAVA之GUI编程菜单 12.JAVA之GUI编程打开与保存文件 13.JAVA之GUI编程将程序打包jar JA

Java并发编程学习笔记(一)线程安全性 1

什么是线程安全性: 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化. 一个对象是否需要线程安全的,取决于他是否被多个线程访问.这指的是在程序中访问对象的方式,而不是对象要实现的功能.要使得对象时线程安全的,需要采用同步机制来协同对对象可变状态的访问.如果无法实现协同,那么可能导致数据破坏以及其他不该出现的结果. 如果当多个线程访

paip.提升效率---filter map reduce 的java 函数式编程实现

#paip.提升效率---filter map reduce 的java 函数式编程实现 ======================================================== #----------------------index索引------------------++函数式编程的优点儿以及缺点++actual code 实际代码例如以下---filter 实现...--- map 实现..---reduce---调用 ##函数式编程的优点儿以及缺点------

java 并发编程读书笔记

1.同步容器,同步容器包括Vector和HashTable,是早期jdk的一部分.另一部分是同步包装类,以Collections.synchronizedxxx的工厂方法创建. 2.同步容器虽然是线程安全的,但是对于复合操作,有时你可能需要加上额外的客户端加锁进行保护,即对于使用这些容器的客户端代码,如果存在复合操作,还是可能存在风险. 3.例如check-and-act操作.循环中的元素操作等,如果在客户端代码中没有额外的锁,都会发生意想不到的问题. 4.造成这些的问题都可以通过在客户端加锁来

Java函数式编程原理以及应用

一. 函数式编程 Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力. 下面来近距离观察一下函数式编程的几个特点: 函数可以作为变量.参数.返回值和数据类型. 基于表达式来替代方法的调用 函数无状态,可以并发和独立使用 函数无副作用,不会修改外部的变量 函数结果确定性:同样的输入,必然会有同样的结果. 下面jdk1.8里面对函数式编程的定义.只是一个  FunctionalInterface 接口.特别的简单. 1 @Documented 2 @Rete

Java并发编程学习笔记

Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现Runnable接口并编写run方法,使得该任务可以执行你的命令.   class MyTask implements Runnable {    private String mName;     public MyTask(String name) {    mName = name;   }  

函数式编程 读书笔记

函数式编程 函数式编程思想:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值. 已经掌握的使用场景: 1.      获取集合中的最大或最小值,当集合类型为自定义类型时的使用比较器 2.      循环进行一些操作.foreEach( ) 3.      统计符合条件的有多少个 List.stream().filter( 条件).count(); .map(  ) : 方法将一个流中的值转换成一个新的流 .filter(   ) :  方法将流进行过滤,保留符合条件的(返回

Java多线程编程(学习笔记)

一.说明 周末抽空重新学习了下多线程,为了方便以后查阅,写下学习笔记. 有效利用多线程的关键是理解程序是并发执行而不是串行执行的.例如:程序中有两个子系统需要并发执行,这时候需要利用多线程编程. 通过多线程的使用,可以编写出非常高效的程序.但如果创建了太多的线程,程序执行的效率反而会降低. 同时上下文的切换开销也很重要,如果创建太多的线程,CPU花费在上下文的切换时间将对于执行程序的时间. 二.Java多线程编程 概念 在学习多线程时,我们应该首先明白另外一个概念. 进程:是计算机中的程序关于某