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

kele2014發表於2017-12-16

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)

if (someOtherSet.contains(candidate))
    result.add(candidate);

// 即使採用Java 8也沒有很大幫助
someSet.stream()

   .filter(someOtherSet::contains)
   .collect(Collectors.toSet());

有些人可能會對函數語言程式設計和Java 8能幫助我們寫出更加簡單、簡潔的演算法持有不同的意見。但這種看法不一定是對的。我們可以把命令式的Java 7迴圈轉換成Java 8的Stream collection,但是我們還是採用了相同的演算法。但SQL風格的表示式則是不同的:
1 SomeSet INTERSECT SomeOtherSet
上面的程式碼在不同的引擎上可以有1000種不同的實現。我們今天所研究的是,在呼叫 INTERSECT 操作之前,更加智慧地將兩個set自動的轉化為 EnumSet 。甚至我們可以在不需要呼叫底層的Stream.parallel() 方法的情況下進行並行 INTERSECT 操作。


相關文章