2014-10-29 50 views
4

我遇到的一種常見模式是需要從數據庫刷新像List或HashMap這樣的集合,但不希望在刷新之間添加或從中刪除值。不可改變但可刷新的集合?

我最近在Google的Guava庫中發現了ImmutableList和ImmutableMap,我非常喜歡它。但我不能對這些類型執行「clearAll()」,也不能重新填充它們。但我喜歡他們是不可改變的。

因此,如果我想強制執行這種「只對數據庫進行可變刷新」的模式,那麼我想每次都必須使用volatile變量。還是有更好的模式?這也可以在多線程環境中,並且我會確保refresh()上沒有競爭條件。

public class MarketManager { 

    private volatile ImmutableList<Market> markets = null; 

    private MarketManager() { 
    } 

    public void refresh() { 
     marketList = //build a new immutable market list 
    } 

    public static MarketManager getInstance() { 
     MarketManager marketManager = new MarketManager(); 
     marketManager.refresh(); 
     return marketManager; 
    } 
} 
+5

你可以使用'Collections.unmodifiableList()';從一個能夠覆蓋該列表的類中的方法返回它。 – fge 2014-10-29 16:52:01

+0

但是如果我想要提高Guava實現的性能呢?我編寫的應用程序使用了大量的集合和大量的內存。 – tmn 2014-10-29 16:53:11

+2

應該指出'Collections.unmodifiableFoos()'返回原始'foo'的不可變視圖,所以它們非常高效。 – Kayaman 2014-10-29 16:56:08

回答

3

這裏是讓你使用Collections.unmodifiableList()你能如何代碼的類:

public class MarketManager { 

    private volatile List<Market> markets = Collections.emptyList(); 

    private MarketManager() { 
    } 

    public void refresh() { 
     marketList = //build a new market list 
    } 

    public List<Market> getMarkets() { 
     return Collections.unmodifiableList(markets); 
    } 

    // ... 
} 

Collections.unmodifiableList()只是封裝任何List實施,使所有的變異操作是「禁用」(即,他們拋出例外)。

1

我想你想混合兩個概念:不可修改的對象和不可變的對象。

不可修改的對象是您無法修改的對象。但是,他們可以被其他參與者「在你之下」改變。當您需要控制對對象內部狀態的訪問時,這些對象很有用。但是,它們對於線程安全性或優化沒有用處。

不可變對象是真正不可變的。一旦創建,它們就不能改變。不是由你,而不是由任何人。它們提供了不可修改對象的所有優點,並且它們允許優化並保證線程安全。

你提出的建議會將不可變集合(創建和凍結)變成不可修改的集合(我無法更改它,但可以從數據庫中刷新它)。只需使用來自Java的不可修改的集合框架,無需改變Guava不可變集合。