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

Java 8 引入了 lambda 表达式,以及函数式编程风格。在了解函数式编程过程中,做了些笔记,摘录于本文。

嵌套函数( Nested Function )

1. 嵌套函数,是指在另一个函数里面定义的一个函数。外层的函数,这里简称为外层函数。

2. 函数的嵌套可以是多层嵌套。嵌套函数可以看到其全部的外层函数的非局部变量。在实际程序中,嵌套的层数一般很少。下面是一个三层嵌套的例子, innerOfInner 也可以访问在 outer 函数体重定义的变量 x 。

function outer(){
    var x = 1;
    function inner(){
        x += 1;
        console.log(x);
        function innerOfInner(){
            x += 10;
            console.log(x);
        }
        return innerOfInner;
    }
    return inner;
}

3. 嵌套函数对非局部变量拥有读和写的权限。

4. 如果一个嵌套函数可以逃离外层函数,例如函数是第一公民,并且内嵌的函数被传到另外一个函数作为参数或者被当做返回值,那么,就会产生一个闭包 ( closure ),通过调用逃离的函数,可以访问函数的原本的环境变量。此时,外层函数的框架 ( frame )会继续存在,直到所有指向此框架的闭包消失。闭包所指向的非局部变量会从栈内存被移到堆内存。

5. Javascript 支持嵌套函数。Java 通过 Lambda 表达式,内部类,匿名类来间接支持内置函数。

例子,add 是外层函数,plus 是嵌套函数。counter 对于 add 来说是局部变量,对于 plus 来说则是非局部变量 ( non-local variable )。在一个外层函数 add 的函数体里面,定义了一个嵌套函数 plus ,然后调用嵌套函数,并返回结果。

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();
    return counter;
}

非局部变量( non-local variable )

1.非局部变量其实是相对的一个称谓,是指既不是局部又不是全局的变量。这个称谓一般用于内嵌的函数,或者匿名函数的上下文当中。

2. 在编程语言中,实现非局部变量比较困难,这也导致了嵌套函数、匿名函数、高阶函数、函数做为第一公民等功能难以实现。

3. 如在上面第 4 点中提到,当嵌套函数被逃离外层函数时,一个闭包就会被产生,并被用于定位非局部变量。当外层函数返回内嵌函数时,外层函数执行完毕,从栈上被弹出,非局部变量也会从栈上消失。但是非局部变量仍然被内存函数引用,所以需要在堆上给他们重新分配内存。这样,非局部变量的生命周期就会长于定义它的外层函数。

非局部变量例子简单例子,参照嵌套函数中 add / plus 的代码以及解释。

闭包 ( Closure )

1. 在操作中,闭包是指一条记录,存储着一个函数和它的环境变量。这个函数既可以是有名函数,也可以是匿名函数。

下面例子中,第一个闭包的函数原来是一个有名函数,而第二个闭包的函数原来是匿名函数。

function f(x) {
    function g(y) {
        return x + y;
    }
    return g;
}

function h(x) {
    return function(y) {
        return x + y
    }
}

var ff = f(3);
ff(5);     // return 8;
var hh = h(3);
hh(5);    // return 8;

闭包可以直接被使用,而不用赋值给其他变量,此时称其为匿名闭包,如下。

f(3)(5);   // return 8

2. 原来的嵌套函数例子中,内嵌的函数在外层函数体内被执行,如果外层函数返回嵌套函数,则产生了一个闭包。见下面例子。

function add() {
    var counter = 0;
    function plus() {
        counter += 1;
        return counter;
    }
    return plus;
}

参考资料

Nested function, wikipedia

Non-local variable, wikipedia

Closure (computer programming), wikipedia

时间: 2024-08-18 23:22:59

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

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

匿名函数 ( Anonymous function ) 1. 匿名函数,是指没有被绑定到标识符的函数.根据字面意思,也可以理解为没有名字的函数. 2. 匿名函数通常: 1). 作为参数,被传递给高阶函数. 2). 作为高阶函数的返回值. 3. 在函数式编程语言,以及其他拥有头等函数的语言中,匿名函数比较普遍. 4. 在一些编程语言中,匿名函数被关键字 lambda 所标记.所以,匿名函数有也被称为Lambda 表达式 ( Lambda express ).例如,Python 就使用 lambda

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多线程编程 概念 在学习多线程时,我们应该首先明白另外一个概念. 进程:是计算机中的程序关于某