天天看點

java性能優化方案10——考慮使用set而并非單個元素

10、考慮使用set而并非單個元素

最後,還有一種情況可以适用于所有語言而并非僅僅同Java有關。除此以外,我們以前研究的N.O.P.E. 分支也會對了解從 O(N3) 到 O(n log n)有所幫助。

不幸的是,很多程式員的用簡單的、本地算法來考慮問題。他們習慣按部就班地解決問題。這是指令式(imperative)的“是/或”形式的函數式程式設計風格。這種程式設計風格在由純粹指令式程式設計向面對象式程式設計向函數式程式設計轉換時,很容易将“更大的場景(bigger picture)”模型化,但是這些風格都缺少了隻有在SQL和R語言中存在的:

聲明式程式設計。

在SQL中,我們可以在不考慮算法影響下聲明要求資料庫得到的效果。資料庫可以根據資料類型,比如限制(constraints)、鍵(key)、索引(indexes)等不同來采取最佳的算法。

在理論上,我們最初在SQL和關系演算(relational calculus)後就有了基本的想法。在實踐中,SQL的供應商們在過去的幾十年中已經實作了基于開銷的高效優化器CBOs (Cost-Based Optimisers)。然後到了2010版,我們才終于将SQL的所有潛力全部挖掘出來。

但是我們還不需要用set方式來實作SQL。所有的語言和庫都支援Sets、collections、bags、lists。使用set的主要好處是能使我們的代碼變的簡潔明了。比如下面的寫法:

SomeSet INTERSECT SomeOtherSet

而不是

// Java 8以前的寫法

Set result = new HashSet();

for (Object candidate : someSet)

// 即使采用Java 8也沒有很大幫助

someSet.stream()

有些人可能會對函數式程式設計和Java 8能幫助我們寫出更加簡單、簡潔的算法持有不同的意見。但這種看法不一定是對的。我們可以把指令式的Java 7循環轉換成Java 8的Stream collection,但是我們還是采用了相同的算法。但SQL風格的表達式則是不同的:

1 SomeSet INTERSECT SomeOtherSet

上面的代碼在不同的引擎上可以有1000種不同的實作。我們今天所研究的是,在調用 INTERSECT 操作之前,更加智能地将兩個set自動的轉化為 EnumSet 。甚至我們可以在不需要調用底層的Stream.parallel() 方法的情況下進行并行 INTERSECT 操作。