你應該更新的 Java 知識之惰性求值:Supplier 和 Guava

在開發中,咱們常常會遇到一些須要延遲計算的情形,好比某些運算很是消耗資源,若是提早算出來卻沒有用到,會得不償失。在計算機科學中,有個專門的術語形容它:惰性求值。惰性求值是一種求值策略,也就是把求值延遲到真正須要的時候。在Java裏,咱們有一個專門的設計模式幾乎就是爲了處理這種情形而生的:Proxy。不過,如今咱們有了新的選擇:Supplier。
咱們先來看看 Supplier 的定義:
public interface Supplier{
	T get();
}
很是簡單的一個定義,簡而言之,獲得一個對象。但它有什麼用呢?咱們能夠把耗資源運算放到get方法裏,在程序裏,咱們傳遞的是Supplier對象,直到調用get方法時,運算纔會執行。這就是所謂的惰性求值。

對於Java這種缺少惰性求值的語言,惰性通常就是經過一個間接層來實現的。David Wheeler曾經說過:「計算機科學中的全部問題均可以經過引入一個間接層解決。」 java

理解了基本的用法,實現一個Supplier並不困難: 程序員

Supplier ultimateAnswerSupplier = new Supplier(){
	@Override
	public Integer get(){
		//Long time computation
		return 42;
	}
};

當咱們須要這個終極答案時,只要: 設計模式

int ultimateAnswer = ultimateAnswerSupplier.get();
確實很簡單,可是,我知道你已經心生另外一個疑問。一般實現 Proxy 模式,咱們只會計算一次,像終極答案這樣的東西,反覆運算咱們可承受不起,也沒有必要。我甚至知道你已經火燒眉毛地打算動手實現本身的解決方案,把結果保留下來,再下次調用時,直接返回結果。但,且慢。不,我並非說多線程併發讓保存結果這件小事變得複雜,由於我相信你的能力。但你是否想過,若是你打算爲它這麼作,也就意味着,你幾乎要爲全部的Supplier對象這麼作。反覆作一件事,顯然不該該是一個程序員的做爲。
幸虧Guava已經給咱們準備好了:
memorizedUltimateAnswerSupplier = Suppliers.memoize(ultimateAnswerSupplier);
memoize() 函數幫我打點了前面所說的那些事情:第一次 get() 的時候,它會調用真正Supplier,獲得結果並保存下來,下次再訪問就返回這個保存下來的值。
有時候,這個值只在一段時間內是有效的,你知道我要說什麼了,Guava還給咱們提供了一個另外一個函數,讓咱們能夠設定過時時間:
expirableUltimateAnswerSupplier = memoizeWithExpiration(target, 100, NANOSECONDS);

好了,還在本身編寫 Proxy 處理惰性求值嗎?Supplier即是你須要更新的 Java 知識。順便說一下,Java 8裏也有 Supplier 哦! 多線程

相關文章
相關標籤/搜索