网站首页 > java教程 正文
在 Java 8 中使用函数式编程生成字母序列是一个很大的挑战。Lukas Eder 愉快地接受了这个挑战,他将告诉我们如何使用 Java 8 来生成ABC的序列——当然,肯定不是一种蹩脚的方式。
我被 Stack Overflow 上网友“mip”提的一个有趣的问题给难住了。该问题是:
1 2 3 |
|
大家应该能够很快认出这是 Excel spreadsheet 的头部,准确的样子如下:
到现在为止,没有一个答案是使用 Java 8 的函数式编程实现的,因此我接受此挑战。我将使用 jOOλ,因为 Java 8 的 Stream API 提供的功能不足以完成该任务(我承认我错了——非常感谢 Sebastian 对这个问题的有趣解答)。
首先,我们用函数的方式分解这个算法。我们所需要的组件有:
1、一个(可重复)的字母表。
2、一个上界,例如想生成多少个字母。如要求生成序列ZZ,那上界就是2。
3、一种将字母表中的字母与先前生成的字母联合成一个笛卡尔积(cartesian product)的方法。
让我们看一下代码:
1、生成字母表
我们可以这样写入字母表,如:
1 |
|
但这很差劲。我们使用 jOOλ 代替:
1 2 3 4 |
|
上面的代码生成从字符 A 到 Z 的封闭区间(Java-8-Stream-speak 是包含上边界的),然后将字符映射成字符串,最后将其转换为列表。
目前为止,一切都很好。现在:
2、使用上边界:
要求的字符序列包括:
1 |
|
但是我们应该很容易想到扩展该需求,能生成如下字符序列,或者更多:
1 |
|
因此,我们将再次使用 rangeClosed:
1 2 3 4 |
|
这种方法是为范围[1..2]中每个长度生成一个单独的流,然后再将这些流合并到一个流中。flatMap 的本质与命令式编程(imperative programming)中的嵌套循环类似。
3、合并字母到一个笛卡尔积中
这是最棘手的部分:我们需要合并字符及出现的次数。因此,我们将使用如下的流:
1 2 3 4 5 |
|
我们再次使用 rangeClosed 来生成范围 [1 .. length-1] 的值。foldLeft 与 reduce 基本一致,区别在于 foldLeft 保证在流中的顺序是从“左至右”的,不需要 fold 函数来关联。
另一方面,这是一个共容易懂的词汇:foldLeft 仅代表一条循环的命令。循环的“起源”(即循环的初始化值)是一个完整的字母表(Seq.seq(alphabet))。现在,在范围 [1..length-1] 中的值生成一个笛卡尔积(crossJoin()),产生一个新的字母表,然后我们将每个合并的字母再组成一个单独的字符串(t.v1 与 t.v2)。
这就是整个过程。
将上面的内容合并到一起
下面是一个简单的打印 A .. Z, AA .. ZZ, AAA .. ZZZ 到控制台的程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
声明
对于这个问题,这确实不是最优的算法。在Stack Overflow,有一个匿名用户给出了一种最好实现方法。
1 2 3 4 5 6 7 8 9 10 |
|
不用说,这个算法比之前的函数式算法会快很多。
51CTO官方微信
焦最新最前沿最有料的IT技术资讯
IT行业精华内容、产品交流心得
微信号:weixin51cto
长按二维码扫描关注
其它推荐:51CTO高招
如果你觉得文章还不错,帮我点个赞哦~
或者分享给更多的人^_^谢谢啦~
- 上一篇: java生成海报(java制作图片)
- 下一篇: 实现扫码登陆的最简单方案与原理(扫码登录的实现)
猜你喜欢
- 2024-09-27 运维干货来啦:Jenkins+gradlew自动构建android项目提供下载链接和二维码下载
- 2024-09-27 基于 Spring Boot 和 WxJava 实现网站接入微信扫码登录
- 2024-09-27 基于token的多平台身份认证架构设计
- 2024-09-27 在线二维码生成器有哪些?微信二维码转换成链接如何实现?
- 2024-09-27 扫二维码提货系统自己建,系统搭建与操作指南分享
- 2024-09-27 PDF文件添加二维码水印(pdf二维码怎么弄出来扫码)
- 2024-09-27 掏出手机,扫一扫,即刻登录——SpringBoot实现二维码扫码登录
- 2024-09-27 短连接生成器有哪些?制作二维码生成器有哪些?
- 2024-09-27 慕课网Java相关课程学习项目源码,以及源码地址
- 2024-09-27 二维码扫描优化(微信二维码优化)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)