ホームページ  >  記事  >  Java  >  Java 構造化データ処理オープンソース ライブラリ SPL について理解しましょう

Java 構造化データ処理オープンソース ライブラリ SPL について理解しましょう

WBOY
WBOY転載
2022-05-24 13:34:591987ブラウズ

この記事では、java に関する関連知識を提供します, 主に構造化データ処理用のオープン ソース ライブラリ SPL に関連する問題を紹介します. java. データ処理クラス ライブラリの理想的な構造を見てみましょう皆様のお役に立てれば幸いです。

Java 構造化データ処理オープンソース ライブラリ SPL について理解しましょう

推奨学習: 「java ビデオ チュートリアル

最新の Java アプリケーション アーキテクチャでは、データのストレージと処理の分離がますます重視されています。一般的なマイクロサービスなど、保守性、拡張性、移植性が向上します。このアーキテクチャでは通常、ビジネス ロジックを従来のアプリケーション アーキテクチャのようにデータベースに配置するのではなく、Java プログラムに実装する必要があります。

アプリケーションのビジネス ロジックのほとんどには、構造化データ処理が含まれます。データベース (SQL) はそのようなタスクを豊富にサポートしており、ビジネス ロジックは比較的簡単に実装できます。しかし、Java にはそのような基本的なサポートが常に欠けており、Java でビジネス ロジックを実装するのは非常に面倒で非効率的でした。その結果、アーキテクチャ上のさまざまな利点にもかかわらず、開発効率が大幅に低下しました。

構造化データ処理および計算クラス ライブラリの完全なセットを Java で提供すれば、開発効率を低下させることなくアーキテクチャの利点を享受できるこの問題は解決できます。

どのような能力が必要ですか?

Java での理想的な構造化データ処理クラス ライブラリにはどのような特性が必要ですか? SQL からそれを要約することができます:

1 セットの計算能力

構造化されたデータは、多くの場合、バッチ (セットの形式) で表示されます。のデータの場合、十分なセット コンピューティング機能を提供する必要があります。

集合演算ライブラリがない場合は、基本的なデータ型である配列(集合に相当)のみが存在するため、集合のメンバーの単純な合計を求める場合には、4 つまたは完了、フィルター、グループ化には 5 行のループ ステートメントが必要で、集計などの操作には数百行のコードが必要です。

SQL は、SUM/COUNT やその他の集計演算などの豊富な演算セットを提供します。WHERE はフィルタリングに使用され、GROUP はグループ化に使用されます。また、交差、和集合、差分などの基本的な演算もサポートしています。セット用。この方法で書かれたコードははるかに短くなります。

2 Lambda 構文

集合演算機能があれば十分ですか? Java 用の集合演算ライブラリのバッチを開発すると、SQL の効果を実現できますか?

それほど単純ではありません!

フィルタリング操作を例に挙げます。通常、フィルタリングには、条件を満たすセット メンバーを保持するための条件が必要です。 SQL では、この条件は式の形で現れます。たとえば、WHERE x>0 と記述することは、x>0 の計算結果を true にするメンバーを保持することを意味します。式 x>0 は、このステートメントの実行前には評価されませんが、反復中に各セット メンバーに対して評価されます。基本的に、この式は本質的に関数であり、現在のコレクションのメンバーをパラメーターとして受け取る関数です。 WHERE 操作の場合、WHERE のパラメーターとして式で定義された関数を使用することと同じです。

ラムダ文法または関数型言語と呼ばれる、この記述方法を表す用語があります。

Lambda 構文がないと、関数を一時的に定義しなければならないことが多く、コードが非常に煩雑になり、名前の競合が発生しやすくなります。

Lambda 構文は SQL で広く使用されています。フィルタリングやグループ化操作には必要ありません。また、計算列などの不必要なシナリオでも使用できるため、コードが大幅に簡素化されます。

3 Lambda 構文でフィールドを直接参照する

構造化データは単純な単一の値ではなく、フィールドを含むレコードです。

SQL 式パラメータでレコード フィールドを参照する場合、ほとんどの場合、フィールドが属するレコードを指定せずにフィールド名を直接使用できることがわかりました。同じ名前のフィールドが複数ある場合にのみ、区別するにはテーブル名 (またはエイリアス) を使用する必要があります。

Java の新しいバージョンも Lambda 構文のサポートを開始しましたが、Lambda 構文で定義された関数に現在のレコードをパラメータとして渡すことしかできず、計算式を記述するときに常にこのレコードを持ち込むことになります。たとえば、単価と数量を使用して金額を計算する場合、現在のメンバーを表すパラメータの名前が x の場合、「x. 単価 * x. 数量」という長い形式で記述する必要があります。 SQL では、「単価 * 数量」としてより直感的に記述することができます。

4 動的データ構造

SQL は動的データ構造も非常に適切にサポートできます。

構造化データの計算では、戻り値は構造化データであることが多く、結果のデータ構造は演算に関連するため、コードを記述する前に準備することはできません。したがって、動的なデータ構造機能をサポートする必要があります。

SQL の SELECT ステートメントは新しいデータ構造を生成します。事前に構造 (クラス) を定義しなくても、コード内で自由にフィールドを追加したり削除したりできます。 Java のような言語ではこれは不可能であり、使用されるすべての構造 (クラス) はコードのコンパイル段階で定義する必要があり、原則として実行中に新しい構造を動的に生成することはできません。

5 インタープリタ型言語

これまでの記事の分析から、すでに結論を導き出すことができます。Java 自体は構造化データ処理の言語としては適していません。その Lambda メカニズムは機能 3 をサポートしておらず、コンパイル言語として機能 4 を実装できません。

実際、前述の Lambda 構文はコンパイル言語での実装には適していません。コンパイラーは、パラメーター位置に書き込まれた式がその場で式の値を計算して渡すべきか、それとも式全体を関数にコンパイルして渡すべきかを判断できず、さらに多くの構文シンボルを追加する必要があります。それを区別するために設計されています。インタプリタ型言語ではこの問題はなく、パラメータとしての式を最初に計算するか、集合メンバーをたどってから計算するかは関数自体で決定できます。

SQL は確かにインタープリタ型言語です。

SPLの紹介

Streamは、Java 8で正式にリリースされた構造化データ処理ライブラリですが、上記の要件を満たしていません。専門的な構造化データ型を持たず、多くの重要な構造化データ計算機能が欠如し、インタープリタ型言語ではなく、動的データ型をサポートせず、Lambda 構文のインターフェイスが複雑です。

Kotlin は Java エコシステムの一部であり、Stream をベースに若干の改良が加えられ、構造化データの計算タイプも提供されていますが、構造化データの計算機能が不十分なため、Anインタープリタ型言語は動的データ型をサポートしておらず、Lambda 構文のインターフェイスも複雑であり、依然として理想的な構造化データ コンピューティング クラス ライブラリとは言えません。

Scala は豊富な構造化データ計算関数を提供しますが、コンパイル言語の特性により、理想的な構造化データ計算クラス ライブラリにはなりません。

それでは、Java エコシステムでは他に何が使用できるでしょうか?

esProc SPL。

SPL は、Java によって解釈および実行されるプログラミング言語であり、豊富な構造化データ計算クラス ライブラリ、シンプルな Lambda 構文、便利で使いやすい動的データ構造を備えており、理想的な構造化処理クラス ライブラリです。 Javaの下で。

豊富な集合演算機能

SPL は、シーケンス テーブルという専門的な構造化データ型を提供します。シーケンステーブルはSQLデータテーブルと同様にバッチレコードの集合であり、構造化データ型の一般的な機能を備えており、以下に例を示します。

ソース データを解析し、シーケンス テーブルを生成します:

Orders=T("d:/Orders.csv")

列名によって元のシーケンス テーブルから新しいシーケンス テーブルを生成します:

Orders.new(OrderID, Amount, OrderDate)

計算列:

Orders.new(OrderID, Amount, year(OrderDate))

フィールドの名前変更:

Orders.new(OrderID:ID, SellerId, year(OrderDate):y)

シリアル番号によるフィールドの使用:

Orders.groups(year(_5),_2; sum(_4))

シーケンス テーブルの名前変更 (左関連付け)

join@1(Orders:o,SellerId ; Employees:e,EId).groups(e.Dept; sum(o.Amount))

シーケンス テーブルはすべての構造化計算関数をサポートし、計算結果もMapなどのデータ型ではなく、シーケンステーブルです。たとえば、グループ化された集計結果の構造化データの処理を続行します。

Orders.groups(year(OrderDate):y; sum(Amount):m).new(y:OrderYear, m*0.2:discount)

SPL は、シーケンス テーブルに基づいて、フィルタリング、並べ替え、グループ化、重複排除、名前変更などの豊富な構造化データ計算機能を提供します。計算列、関連付け、サブクエリ、集合計算、順序付け計算など。これらの関数は強力なコンピューティング機能を備えており、ハードコーディングの支援なしで独立して計算を完了できます。

結合クエリ:

Orders.select(Amount>1000 && Amount<=3000 && like(Client,"*bro*"))

並べ替え:

Orders.sort(-Client,Amount)

グループ サマリー:

Orders.groups(year(OrderDate),Client; sum(Amount))

内部関連付け:

join(Orders:o,SellerId ; Employees:e,EId).groups(e.Dept; sum(o.Amount))

単純な Lambda 構文

SPL は単純な Lambda 構文をサポートしています。関数名と関数本体を定義する必要はありません。直接使用できます。式 as フィルタリングなどの関数のパラメータとして:

Orders.select(Amount>1000)

ビジネス ロジックを変更する場合、関数を再構築する必要はなく、単に式を変更するだけです:

Orders.select(Amount>1000 && Amount<2000)

SPL はインタープリタ型言語です。パラメーター式を使用します。パラメーターの型を明示的に定義する必要がないため、Lambda インターフェイスがよりシンプルになります。たとえば、合計処理中に二乗和を計算したい場合は、次のように直感的に記述できます。

Orders.sum(Amount*Amount)

SQL と同様に、SPL 構文では、単一テーブルの計算でのフィールド名の直接使用もサポートされています。

Orders.sort(-Client, Amount)

動的データ構造

SPL は、動的データ構造を自然にサポートし、計算結果の構造に基づいて新しいシーケンスを動的に生成できるインタープリター言語です。これは、計算列、グループ集計、相関関係などの計算に特に適しています。たとえば、グループ集計の結果を直接再計算する:

Orders.groups(Client;sum(Amount):amt).select(amt>1000 && like(Client,"*S*"))

または相関計算の結果を直接再計算する:

join(Orders:o,SellerId ; Employees:e,Eid).groups(e.Dept; sum(o.Amount))

より複雑なもの 通常、計算は複数のステップに分かれており、各中間結果のデータ構造はほとんど異なります。 SPL は、最初にこれらの中間結果の構造を定義する必要がなく、動的データ構造をサポートします。例えば、ある年の顧客支払実績表をもとに、月々の支払額上位10社を計算します。

Sales2021.group(month(sellDate)).(~.groups(Client;sum(Amount):sumValue)).(~.sort(-sumValue)) .(~.select(#<=10)).(~.(Client)).isect()

SQL

SPLを直接実行します。 SQL インタープリタを実装しており、SQL を直接実行できます。基本的な WHERE、GROUP から JOIN、さらには WITH まですべてをサポートできます。処理言語である SPL は、SQL のすべてのコンピューティング機能をカバーするだけでなく、言語の点でさらに強力な利点もあります。

離散性と、より完全な集計のサポート

Collection は SQL の基本機能であり、セットの形式で操作に参加するデータをサポートします。ただし、SQL の離散的な性質は非常に貧弱で、すべてのセットのメンバーは全体として操作に参加する必要があり、セットから分離することはできません。 Java などの高級言語は良好な離散性をサポートしており、配列メンバーを独立して操作できます。

但是,更彻底的集合化需要离散性来支持,集合成员可以游离在集合之外,并与其它数据随意构成新的集合参与运算 。

SPL兼具了SQL的集合化和Java的离散性,从而可以实现更彻底的集合化。

比如,SPL中很容易表达“集合的集合”,适合分组后计算。比如,找到各科成绩均在前10名的学生:


A
1=T(“score.csv”).group(subject)
2=A2.(.rank(score).pselect@a(<=10))
3=A1.(~(A3(#)).(name)).isect()
SPL序表的字段可以存储记录或记录集合,这样可以用对象引用的方式,直观地表达关联关系,即使关系再多,也能直观地表达。比如,根据员工表找到女经理下属的男员工:
Employees.select(性别:"男",部门.经理.性别:"女")

有序计算是离散性和集合化的典型结合产物,成员的次序在集合中才有意义,这要求集合化,有序计算时又要将每个成员与相邻成员区分开,会强调离散性。SPL兼具集合化和离散性,天然支持有序计算。

具体来说,SPL可以按绝对位置引用成员,比如,取第3条订单可以写成Orders(3),取第1、3、5条记录可以写成Orders([1,3,5])。

SPL也可以按相对位置引用成员,比如,计算每条记录相对于上一条记录的金额增长率:Orders.derive(amount/amount[-1]-1)

SPL还可以用#代表当前记录的序号,比如把员工按序号分成两组,奇数序号一组,偶数序号一组:Employees.group(#%2==1)

更方便的函数语法

大量功能强大的结构化数据计算函数,这本来是一件好事,但这会让相似功能的函数不容易区分。无形中提高了学习难度。

SPL提供了特有的函数选项语法,功能相似的函数可以共用一个函数名,只用函数选项区分差别。比如select函数的基本功能是过滤,如果只过滤出符合条件的第1条记录,只须使用选项@1:

Orders.select@1(Amount>1000)

数据量较大时,用并行计算提高性能,只须改为选项@m:

Orders.select@m(Amount>1000)

对排序过的数据,用二分法进行快速过滤,可用@b:

Orders.select@b(Amount>1000)

函数选项还可以组合搭配,比如:

Orders.select@1b(Amount>1000)

结构化运算函数的参数常常很复杂,比如SQL就需要用各种关键字把一条语句的参数分隔成多个组,但这会动用很多关键字,也使语句结构不统一。

SPL支持层次参数,通过分号、逗号、冒号自高而低将参数分为三层,用通用的方式简化复杂参数的表达:

join(Orders:o,SellerId ; Employees:e,EId)

扩展的Lambda语法

普通的Lambda语法不仅要指明表达式(即函数形式的参数),还必须完整地定义表达式本身的参数,否则在数学形式上不够严密,这就让Lambda语法很繁琐。比如用循环函数select过滤集合A,只保留值为偶数的成员,一般形式是:

A.select(f(x):{x%2==0} )

这里的表达式是x%2==0,表达式的参数是f(x)里的x,x代表集合A里的成员,即循环变量。

SPL用固定符号~代表循环变量,当参数是循环变量时就无须再定义参数了。在SPL中,上面的Lambda语法可以简写作:A.select(~ %2==0)

普通Lambda语法必须定义表达式用到的每一个参数,除了循环变量外,常用的参数还有循环计数,如果把循环计数也定义到Lambda中,代码就更繁琐了。

SPL用固定符号#代表循环计数变量。比如,用函数select过滤集合A,只保留序号是偶数的成员,SPL可以写作:A.select(# %2==0)

相对位置经常出现在难度较大的计算中,而且相对位置本身就很难计算,当要使用相对位置时,参数的写法将非常繁琐。

SPL用固定形式[序号]代表相对位置


A B
1 =T(“Orders.txt”) /订单序表
2 =A1.groups(year(Date):y,month(Date):m; sum(Amount):amt) /按年月分组汇总
3 =A2.derive(amt/amt[-1]:lrr, amt[-1:1].avg():ma) /计算比上期和移动平均

无缝集成、低耦合、热切换

作为用Java解释的脚本语言,SPL提供了JDBC驱动,可以无缝集成进Java应用程中。

简单语句可以像SQL一样直接执行:

…
Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
PrepareStatement st = conn.prepareStatement("=T(\"D:/Orders.txt\").select(Amount>1000 && Amount<=3000 && like(Client,\"*S*\"))");
ResultSet result=st.execute();
...

复杂计算可以存成脚本文件,以存储过程方式调用

…
Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
Statement st = connection.();
CallableStatement st = conn.prepareCall("{call splscript1(?, ?)}");
st.setObject(1, 3000);
st.setObject(2, 5000); 
ResultSet result=st.execute();
...

将脚本外置于Java程序,一方面可以降低代码耦合性,另一方面利用解释执行的特点还可以支持热切换,业务逻辑变动时只要修改脚本即可立即生效,不像使用Java时常常要重启整个应用。这种机制特别适合编写微服务架构中的业务处理逻辑。

推荐学习:《java视频教程

以上がJava 構造化データ処理オープンソース ライブラリ SPL について理解しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。