JAVA开发中常常会遇到不方便使用数据库,但又要进行结构化数据计算的场景。JAVA晚期没有提供相干类库,即便排序、分组这种根本计算也要硬写代码,开发效率很低。起初JAVA8推出了Stream库,凭借Lambda表达式、链式编程格调、汇合函数,才终于解决了结构化数据计算类库从无到有的问题。
Stream能够简化结构化数据的计算
比方排序:
Stream<Order> result=Orders.sorted((sAmount1,sAmount2)->Double.compare(sAmount1.Amount,sAmount2.Amount)).sorted((sClient1,sClient2)->CharSequence.compare(sClient2.Client,sClient1.Client));
下面代码中的sorted是汇合函数,可不便地进行排序。"(参数)->函数体"的写法即Lambda表达式,能够简化匿名函数的定义。两个sorted函数连在一起用属于链式编程格调,能够使多步骤计算变得直观。
Stream计算能力还不够强
依然以下面的排序为例,sorted函数只须要晓得排序字段和程序/逆序就够了,参考SQL的写法"…from Orders order by Client desc, Amount",但实际上还要额定输出排序字段的数据类型。程序/逆序用asc/desc(或+/-)等符号就能够简略示意了,但这里却要用compare函数。另外,理论要排序的字段程序和代码写进去的程序是相同的,有些反直觉。
再比方分组汇总:
Calendar cal=Calendar.getInstance();Map<Object, DoubleSummaryStatistics> c=Orders.collect(Collectors.groupingBy( r->{ cal.setTime(r.OrderDate); return cal.get(Calendar.YEAR)+"_"+r.SellerId; }, Collectors.summarizingDouble(r->{ return r.Amount; }) )); for(Object sellerid:c.keySet()){ DoubleSummaryStatistics r =c.get(sellerid); String year_sellerid[]=((String)sellerid).split("_"); System.out.println("group is (year):"+year_sellerid[0]+"\t (sellerid):"+year_sellerid[1]+"\t sum is:"+r.getSum()+"\t count is:"+r.getCount()); }
下面代码中,所有呈现字段名的中央,都要先写上表名,即"表名.字段名",而不能像SQL那样省略表名。匿名函数语法简单,随着代码量的减少,复杂度迅速增长。两个匿名函数造成嵌套,代码更难解读。实现一个分组汇总性能要用多个函数和类,包含groupingBy、collect、Collectors、summarizingDouble、DoubleSummaryStatistics等,学习老本不低。分组汇总的后果是Map,而不是结构化数据类型,如果要持续计算,通常要定义新的结构化数据类型,并进行转换类型,处理过程很繁琐。两个分组字段在结构化数据计算中很常见,但函数grouping只反对一个分组变量,为了让一个变量代表两个字段,就要采取一些变通技巧,比方新建一个两字段的结构化数据类型,或者把两个字段用下划线拼起来,这让代码变得更加繁琐。
Stream计算能力有余,起因在于其根底语言JAVA是编译型语言,无奈提供业余的结构化数据对象,短少来自底层的无力反对。
JAVA是编译型语言,返回值的构造必须当时定义,遇到较多的两头步骤时,就要定义多个数据结构,这不仅让代码变得繁琐,还导致参数解决不灵便,要用一套简单的规定来实现匿名语法。解释性语言则人造反对动静构造,还能够不便地将参数表达式指定为值参数或函数参数,提供更简略的匿名函数。
在这种状况下,Kotlin应运而生。Kotlin是基于JAVA的古代开发语言,所谓古代,重点体现在对JAVA语法尤其是Stream的改良上,即Lambda表达式更加简洁,汇合函数更加丰盛。
Kotlin计算能力强于Stream
比方排序:
var resutl=Orders.sortedBy{it.Amount}.sortedByDescending{it.Client}
下面代码毋庸指明排序字段的数据类型,毋庸用函数表白程序/逆序,间接援用it作为匿名函数的默认参数,而不是刻意定义,整体比Stream简短不少。
Kotlin改良并不大,计算能力依然有余
依然以排序为例,Kotlin尽管提供了it这个默认参数,但实践上只有晓得字段名就够了,没必要带上表名(it)。排序函数只能对一个字段进行排序,不能动静接管多个字段。
再比方分组汇总:
data class Grp(var OrderYear:Int,var SellerId:Int)data class Agg(var sumAmount: Double,var rowCount:Int)var result=Orders.groupingBy{Grp(it.OrderDate.year+1900,it.SellerId)} .fold(Agg(0.0,0),{ acc, elem -> Agg(acc.sumAmount + elem.Amount,acc.rowCount+1) }).toSortedMap(compareBy<Grp> { it. OrderYear}.thenBy { it. SellerId})result.forEach{println("group fields:${it.key.OrderYear}\t${it.key.SellerId}\t aggregate fields:${it.value.sumAmount}\t${it.value.rowCount}") }
下面代码中,一个分组汇总的动作,须要用到多个函数,包含简单的嵌套函数。用到字段的中央要带上表名。分组汇总的后果不是结构化数据类型。要当时定义两头后果的数据结构。
如果持续考查汇合、关联等更多的计算,就会发现同样的法则:Kotlin代码确实比Stream短一些,但大都是无关紧要的质变,并未产生粗浅的量变,该有的步骤一个不少。
Kotlin也不反对动静数据结构,无奈提供业余的结构化数据对象,难以真正简化Lambda语法,无奈脱离表名间接援用字段,无奈间接反对动静的多字段计算(比方多字段排序)。
esProc SPL的呈现,将会彻底改观JAVA生态下结构化数据处理的窘境。
esProc SPL是JVM下的开源结构化数据计算语言,提供了业余的结构化数据对象,内置丰盛的计算函数,灵便简洁的语法,易于集成的JDBC接口,善于简化简单计算。
SPL内置丰盛的计算函数实现根底计算
比方排序:=Orders.sort(-Client, Amount)
SPL毋庸指明排序字段的数据类型,毋庸用函数指明方向/逆序,应用字段时毋庸附带表名,一个函数就能够动静地对多个字段进行排序。
分组汇总:=Orders.groups(year(OrderDate),Client; sum(Amount),count(1))
下面的计算结果依然是结构化数据对象,能够直接参与下一步计算。对双字段进行分组或汇总时,也不须要当时定义数据结构。整体代码没有多余的函数,sum和count用法简洁易懂,甚至很难发觉这是嵌套的匿名函数。
更多计算也同样简略:
去重:=Orders.id(Client)
含糊查问:=Orders.select(Amount*Quantity>3000 && like(Client,“S”))
关联:=join(Orders:o,SellerId ; Employees:e,EId).groups(e.Dept; sum(o.Amount))
SPL提供了JDBC接口,可被JAVA代码无缝调用
Class.forName("com.esproc.jdbc.InternalDriver");Connection connection =DriverManager.getConnection("jdbc:esproc:local://");Statement statement = connection.createStatement();String str="=T(\"D:/Orders.xls\"). Orders.groups(year(OrderDate),Client; sum(Amount))";ResultSet result = statement.executeQuery(str);
SPL语法格调简洁灵便,具备弱小的计算能力。
SPL可简化分步计算、有序计算、分组后计算等逻辑较简单的计算,很多SQL/存储过程难以实现的计算,用SPL解决起来就很轻松。比方,找出销售额累计占到一半的前n个大客户,并按销售额从大到小排序:
除了计算能力,SPL在零碎架构、数据源、两头数据存储、计算性能上也有一些特有的劣势,这些劣势有助于SPL进行库外结构化数据计算。
SPL反对计算热切换和代码外置,可升高零碎耦合性。
比方,将下面的SPL代码存为脚本文件,再在JAVA中以存储过程的模式调用文件名:
Class.forName("com.esproc.jdbc.InternalDriver");Connection connection =DriverManager.getConnection("jdbc:esproc:local://");Statement statement = connection.createStatement();ResultSet result = statement.executeQuery("call getClient()");
SPL是解释型语言,批改后可间接运行,毋庸编译,不用重启JAVA服务。SPL代码外置于JAVA,通过文件名被调用,不依赖JAVA代码,耦合性低。
SPL反对多种数据源,可进行跨源计算和跨库计算。
SPL反对各类数据库,txt\csv\xls等文件,MongoDB、Hadoop、redis、ElasticSearch、Kafka、Cassandra等NoSQL,特地地,还反对WebService XML、Restful Json等多层数据:
对文本文件和数据库进行跨源关联:
SPL提供了自有存储格局,可长期或永恒存储数据,并进行高性能计算。
SPL反对btx存储格局,适宜暂存来自于低速数据源的数据,比方CSV:
btx体积小,读写速度快,能够像一般文本文件那样进行计算:
=T(“D:/fast.btx”).sort(Client,- Amount)
如果对btx进行有序存储,还能取得高计算性能,比方并行计算、二分查找。SPL还反对更高性能的ctx存储格局,反对压缩、列存、行存、分布式计算、大并发计算,适宜长久存储大量数据,并进行高性能计算。
在数据库外的结构化数据计算方面,Stream做出了突破性的奉献;Kotlin增强了这种能力,但编译性语言的个性使它无奈走得更远;要想彻底解决库外计算的难题,还须要SPL这种业余的结构化数据计算语言。
以上就是分享的全部内容,如果喜爱帮忙点赞分享转发,