2014-10-29 65 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不可变集合。