Java Stream API 能取代 SQL 吗?

 

Java SE 8 引入了 Stream API,这种新的代码编写方式与之前处理集合的方式大不相同,只用 filter、map、reduce 和 iterate 组合起来,就可以编写简洁而富有表现力的数据处理查询。基于这个原因,很多程序员尝试用 Stream 取代 SQL。但实际上,Stream 的专业程度还远不如 SQL。

当集合的成员是简单数据类型时(整数、浮点、字符串、日期),Stream 可方便地实现集合计算。但结构化计算的数据对象不是简单数据类型,而是记录(Map\ entity\ record)。一旦数据对象变成记录,Stream 就不那么方便了。Stream 不直接支持关联计算,硬编码实现的关联计算不仅冗长,而且逻辑复杂,编写起来难度更大,这对专业 JAVA 程序员来说都是个挑战。

其实对于大多数习惯用 SQL 操作数据的程序员,如果使用Open-esProc计算包,在没有 SQL 时也能获得 SQL 的好处,弥补了 Stream 的不足。其用法类似用 SQL 计算数据集,在程序中调用其封装后 SPL 计算脚本。例如 “找出英语平均分低于 70 分的班级”,大多数数据库这样操作,“select CLASS,avg(English) as avg_En from students_scores group by CLASS having avg(English)<70”,用 SPL 代码这样实现:


A

1

=file(“E:/txt/Students_scores.csv”).import@tc()

2

=A1.groups(CLASS;avg(English):avg_En)

3

=A2.select(avg_En<70)

完成上述任务,直接用 Stream 其实也不复杂,但没有用 SPL 简单易学。将脚本文件(比如 condition.dfx)和 Java 存储在一起,通过 JDBC 接口在 JAVA 中调用,用法类似存储过程。这样,SPL 计算过程都是独立的,当遇到需求变动后,改动也非常方便。

…
 ResultSet result = statement.executeQuery("call condition.dfx");
…

SPL 也支持类似 SQL 的用法,无须脚本文件,直接将其嵌入 JAVA

…
 ResultSet result = statement.executeQuery("
=file(\“E:/txt/Students_scores.csv\”).import@tc()
.groups(CLASS;avg(English):avg_En).select(avg_En<70)");
…

SPL 中还提供了用 SQL 查询数据的方法,方便熟悉 SQL 的程序直接使用。比如:州信息,部门信息和员工信息分别存储在三个文本文件中(将三个文件换成三个 SPL 序表对象也同样成立),查询经理在 California 州的 New York 州员工。


A

1

$select   e.NAME as ENAME
from   E:/txt/EMPLOYEE.txt  as e
     join E:/txt/DEPARTMENT.txt as d on   e.DEPT=d.NAME
     join E:/txt/EMPLOYEE.txt  as emp on d.MANAGER=emp.EID
where   e.STATE='New York' and emp.STATE='California'

当数据很大时,内存大小就会形成处理的瓶颈,SPL 还通过游标读取的方式,类似数据库中的游标,做小批量读取,然后在游标上绑定计算,实现排序、关联和分组计算,这样就可以利用小内存完成大数据的计算。


A

1

=file("E:/txt/Employees.txt").cursor@t().sortx(EId)

2

=file("E:/txt/Orders.txt").cursor@t().sortx(SellerId)

3

=joinx(A2:O,SellerId; A1:E,EId)

4

=A3.groups(E.Dept;sum(O.Amount))

大数据处理经常需要加入并行计算提高计算效率,每个线程各自计算的方式处理一段数据,最后将各线程处理的结果进行汇总。

A
1 =file(“E:/txt/user_info_reg.csv”).cursor@tcm(;4)
2 =A1.groups(id_province;count(~):cnt)

在 SPL 中使用并行提速非常容易,@m 表示并行计算,参数 4 表示 4 路并行,与单线程代码相比,仅仅多一个游标选项与参数,让用户使用并行非常方便。

利用 SPL 可以极大简化 Java 程序中的结构化数据计算,示例总结整理如下:

集合上的循环运算

序号访问成员

有序集合上的定位计算

有序集合上的对位运算

TopN 运算

存在判断

从属判断

非常规聚合

对齐分组

选出运算

更多计算示例,参见 SPL 应用计算