我提出這部分減少2個用例:
1.解析SQL和PL/SQL(甲骨文程序)語句
SQL語句的標準分隔符是分號(;
)。它將正常的SQL語句彼此分開。但是,如果你有PL/SQL語句,那麼分號將語句內部的運算符彼此分開,而不僅僅是語句。
一個解析的腳本文件同時包含普通的SQL和PL/SQL語句的方法是先用分號,如果特定語句與特定的關鍵字(DECLARE
,BEGIN
等)開始加入與未來這種說法分裂他們,然後語句遵循PL/SQL語法規則。
順便說一句,這不能通過使用StreamEx
部分減少操作來完成,因爲它們只測試兩個相鄰元素。由於您需要了解從最初的PL/SQL關鍵字元素開始的前一個流元素,以確定是否將當前元素包含在部分縮減或部分縮減中。在這種情況下,可變部分縮小可用於收集器保存已收集元素的信息,某些Predicate
只測試收集器本身(如果部分縮小應完成)或測試收集器和當前流元素。理論上講,我們講的是使用流管道思想來實現LR(0)或LR(1)解析器(請參閱https://en.wikipedia.org/wiki/LR_parser)。 LR解析器可以用來解析大多數編程語言的語法。
解析器是一個有限自動機的堆棧。在LR(0)自動機的情況下,其轉換僅取決於堆棧。在LR(1)自動機的情況下,它取決於來自流的棧和下一個元素(理論上可以有LR(2),LR(3)等自動機窺視2,3等下一個元素來確定轉換,但在實踐中,所有的編程語言都是語法LR(1)語言)。
要實現解析器,應該包含一個包含有限自動機堆棧和謂詞測試的Collector
,以確定是否達到了此自動機的最終狀態(因此我們可以停止還原)。在LR(0)的情況下,它應該是Predicate
測試Collector
本身。在LR(1)的情況下,它應該是BiPredicate
測試Collector
和流中的下一個元素(因爲轉換取決於堆棧和下一個符號)。
所以實現LR(0)分析器,我們將需要像以下的(T
是流元素類型,A
是累加器保持兩個有限自動機堆棧和結果,R
是每個語法分析器工作形成輸出流的結果):
<R,A> Stream<R> Stream<T>.parse(
Collector<T,A,R> automataCollector,
Predicate<A> isFinalState)
(我刪除了複雜像? super T
而不是T
緊湊性 - 結果API應該包含這些)
要實現LR(1)語法分析器,我們需要類似以下內容:
<R,A> Stream<R> Stream<T>.parse(
BiPredicate<A, T> isFinalState
Collector<T,A,R> automataCollector)
注意:在這種情況下BiPredicate
應它將通過蓄電池消耗之前測試元件。記住LR(1)解析器正在窺視下一個元素以確定轉換。因此,如果空累加器拒絕接受下一個元素(BiPredicate
返回true,表示部分減少已結束,在由Supplier
創建的空累加器和下一個流元素上),則可能有異常。
2.根據流元件類型條件配料
當我們執行我們要相鄰數據修改(DML)語句合併成一個單一批次SQL statemens(見JDBC API),以提高整體性能。但我們不想批量查詢。所以我們需要條件批處理(而不是像Java 8 Stream with batch processing那樣的無條件批處理)。
對於這種特定情況StreamEx
可以使用部分縮減操作,因爲如果BiPredicate
測試的兩個相鄰元素都是DML語句,則它們應該包含在批處理中。所以我們不需要知道以前批量採集的歷史。
但是,我們可以增加任務的複雜性,並說批次應該受到大小的限制。假設一批中不超過100個DML語句。在這種情況下,我們不能忽略先前的批次收集歷史並使用BiPredicate
來確定批次收集是應該繼續還是停止不足。
雖然我們可以在StreamEx
部分減少之後添加flatMap以將長批次拆分成部分。但是這會延遲特定的100個元素的批處理執行,直到所有的DML語句都被收集到無限批量中。毋庸置疑,這與管道意識形態相反:我們希望最大限度地減少緩衝,以最大限度地提高輸入和輸出之間的速度。此外,如果DML語句的列表非常長而無任何查詢(例如,由於數據庫導出而導致的數百萬個INSERT
),則無限批量收集可能導致OutOfMemoryError
不可容忍。
因此,在這種複雜的有條件的批量收集的情況下,我們也需要像在前面的用例中描述的LR(0)解析器那樣強大的功能。
這似乎是一個很糟糕的主意。地圖操作應該是無副作用的。你幾乎可以肯定應該做的就是調用'Stream.iterator()',並通過移動迭代器直到你碰到''這樣的「舊派」方式。 –
2014-12-03 23:38:47
或多或少,流並不打算以這種方式使用。迭代器是更合理的方法。 – 2014-12-03 23:44:36
* facepalm * 這是完全正確的。 #編碼 – limbo 2014-12-04 03:22:58