Java函数式编程简介:理解编程范式与数学函数的关系

1. 概述

Java函数式编程简介:理解编程范式与数学函数的关系

1.1 函数式编程简介

Java 是面向对象的编程语言。若按照编程种类来划分的话,它属于命令式编程(Imperative Programming)。常见的编程范式除了命令式编程之外,还有逻辑式编程(Logic Programming)以及函数式编程(Functional Programming)。

函数式编程是一种编程范式。在科学领域,它是编写计算机程序数据结构和元素的一种方式。它把计算过程当作数学函数的求值,并且避免更改状态和可变数据。

什么是函数式编程?简单来说,就是一切都可以被视为数学函数。在函数式编程语言中,同样可以存在对各种数据的操作和处理。

象,通常这些对象是恒定不变的。这些对象要么是函数参数,要么是函数返回值。在函数式编程语言中没有 for/next 循环,因为这种逻辑意味着有状态的改变。取而代之的是,这种循环逻辑在函数式编程语言中是通过递归以及把函数当成参数传递的方式来实现的。

2. Lambda 表达式

Java 8 有一个最大的变化,那就是引入了 Lambda 表达式。Lambda 是希腊字母 λ 的英文名称,它是一种非常紧凑的、能够传递行为的方式。

2.1 Lambda 表达式的形式

lambda 表达式的语法包含参数列表、箭头符号“->”以及函数体。其中,函数体可以是一个表达式,同时也可以是一个语句块。

表达式:表达式会被执行然后返回执行结果。

语句块:语句块中的语句会被依次执行,就像方法中的语句一样。

return语句会把控制权交给匿名方法的调用者。

break和continue只能在循环中使用。

函数体有返回值时,函数体内部的每一条路径都必须有返回值。

表达式函数体适用于小型 lambda 表达式,它把 return 关键字给消除了,从而让语法变得更加简洁。以下是一些 lambda 表达式:

(int x, int y) ‐> x + y 
( ) ‐> 42
对于字符串 s ,会执行输出 s 的操作 。即会将字符串 s 输出到控制台 。

第一个 lambda 表达式会接收两个整形参数,然后将它们相加并返回结果;第二个 lambda 表达式则进行着其他相关的操作。

第一个 lambda 表达式不接收参数,会返回整数“42”;第二个 lambda 表达式接收一个字符串并将其打印到控制台,不返回任何值。

2.2 常见应用

2.2.1 替代匿名内部类

毫无疑问,lambda 表达式使用最多的场合是替代匿名内部类。实现 Runnable 接口是匿名内部类的一个经典例子。lambda 表达式的功能十分强大,仅用“()->”就能够替代整个匿名内部类!请看以下代码:

如果使用匿名内部类:

@Test
public void oldRunable() {
创建一个新的线程,该线程实现了 Runnable 接口。在重写的 run 方法中执行具体的任务。
public void run() {
System 正在打印“旧的可运行对象现在正在被使用!”;
}
}).start();
}

而如果使用lambda表达式:

@Test
public void runable() {
创建一个新的线程,该线程的执行体是输出 "It's a lambda function!",然后启动这个线程。
}

最后的输出:

The old runable now is using!
  It's a lambda function!

它是否强大得令人害怕?它是否简单得令人害怕?它是否清晰明了且重点突出得令人害怕?这便是

lambda 表达式很可怕,它用极少的代码就完成了之前一个类所做的事情。

2.2.2 使用lambda表达式对集合进行迭代

Java 的集合类在日常开发中被经常使用,甚至可以说在每一个 Java 代码中都可能会使用到集合类。而对于集合类最常见的操作就是进行迭代遍历。请看对比:

@Test
public void iterTest() {
List语言有 java、scala、python,这些语言被包含在一个列表中,该列表由 Arrays.asList 方法生成。
//before java8
对于每一个 String 类型的元素 each ,在 languages 中,系统会输出 each 。
}
//after java8
对于 languages 中的每一个元素 x,都会输出 x。即依次遍历 languages 中的每个元素,并将其打印出来。
对于每一种语言,都将其输出到控制台。
}

熟悉 scala 的同学肯定知晓 forEach 。它能够对集合里的所有对象进行迭代,同时会将

lambda表达式带入其中。

遍历 languages 这个集合,对于集合中的每一个元素,都将其输出到控制台。

这一行的样子有点像 c++中作用域解析的那种写法,并且在这里是可以使用的。

2.2.3 用lambda表达式实现map

提到函数式编程时,提到 lambda 表达式时,就不能不提 map。确实,java8 是支持的。以下是示例代码:

@Test
public void mapTest() {
List然后使用 forEach 方法对转换后的每个元素进行操作。
System.out.println(x));
}

最后的输出结果:

10.5
21.0
31.5

map 函数在函数式编程中是极为重要的一个方法。map 的主要作用是把一个对象转变为另一个对象。在我们所举的例子里,借助 map 方法把 cost 增大了 0.05 倍并输出。

2.2.4 用lambda表达式实现map与reduce

提到了 map 后,就不能不提到 reduce。reduce 如同 map 一样,是函数式编程中最重要的几个方法之一。map 的功能是把一个对象转变为另一个对象,而 reduce 实现的是把所有的值合并为一个,如下所示:

@Test
public void mapReduceTest() {
Listcost 是一个包含 10.0、20.0、30.0 的数组列表。
首先获取成本流 cost.stream(),然后对每个元素 x 进行计算,即 x 加上 x 乘以 0.05,也就是 x + x * 0.05,接着使用 reduce 方法对这些计算结果进行累加操作,将累加的结果存储在 doubleAllCost 中。
‐> sum + x).get();
System.out.println(allCost);
}

最终的结果为:

63.0

如果我们用for循环来做这件事情:

@Test
public void sumTest() {
Listcost 包含 10.0、20.0 和 30.0 ;double 类型的 sum 初始值为 0 ;
对于每一个 double 类型的 each :它在 cost 中。然后 each 自身加上 each 乘以 0.05 的结果。接着 sum 加上 each 。
}
System.out.println(sum);
}

相信使用 map+reduce+lambda 表达式的写法要高出一定程度。

2.2.5 filter操作

filter 是我们时常使用的一种操作。在对集合进行操作时,常常需要从原本的集合里把一部分元素过滤掉。

@Test
public void filterTest() 
List cost = Arrays.as
包含 10.0、20.0、30.0、40.0 的列表;这个列表;有 10.0、20.0、30.0、40.0 的列表;列表中包含 10.0、20.0、30.0、40.0;以 10.0、20.0、30.0、40.0 构成的列表cost 进行流操作,通过 filter 方法筛选出大于 25.0 的元素,然后使用 collect 方法将筛选后的元素收集为一个列表,最终得到 filteredCost 。
对于 filteredCost 中的每一个 x,都会执行 System.out.println(x) 操作。
}

最后的结果:

30.0
40.0

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

24阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

27阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

23阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读