【问题标题】:Java cache design questionJava缓存设计题
【发布时间】:2011-02-23 01:11:55
【问题描述】:

我需要开发一个简单的缓存(不需要并发或刷新)来保存不同类型的对象。这些对象的查找可能采用不同的方式。就像假设我们正在缓存具有 ISBN 号和作者的书籍对象。此对象的查找可以通过 ISBN 编号,如

图书查找BookByISBN(String isbn);

或者它可能是一个lookupByAuthor,比如

List lookupBookByAuthor(String authorName);

以一种非常简单的方式,这意味着我可以拥有一个 Cache 对象,该对象有两个映射,一个用于按 ISBN 存储图书对象,另一个用于按作者姓名存储相同的对象。

像这样,想想很多像书这样的对象类型,所以我不想因为它们的查找不同而将同一个对象存储在不同的地图中。

我正在考虑使用单个 Map 的一种方式,其键是自定义 Key 对象,值是 Object(这样我就可以存储任何对象或对象列表) Key 对象是一个不可变对象,可能看起来像这样

public class Key {   
      private final Stirng keyName;   
      private final String keyValue;   
      public Key(String name,String value) {
          this.keyName= name;
          this.keyValue = value;   
      }    
     //getters for keyName and value 
     //hashcode and equals to be put as a key of a map
}

查找方法的实现将是

public Book lookupBookByISBN(String isbn) {
    Key key = new Key("ISBN",isbn);
    return ((Book)map.get(key));
}

public List<Book> lookupBookByAuthor(String isbn) {
        Key key = new Key("Author",isbn);
        return (List<Book>map.get(key));
    }

插入地图需要小心,因为同一个对象需要两次插入地图。

public void putBook(Book book) {
   Key key = new Key("ISBN",book.getISBN());
   map.put(key,book);
   key = new Key("Author",book.getAuthor());
   List<Book> list = map.get(key);
   if (null == list) {
      list = new ArrayList<Book>();
      map.put(key,book);
   }
   list.add(book);

}

不知何故,我觉得这可能不是一个好主意,我可能需要在地图中放置同一个对象 N 次,具体取决于我需要查找对象的 N 个维度。

还有其他更好的方式来设计相同的吗?

【问题讨论】:

  • 我建议为不同的查找类型使用不同的地图。这样您就不需要复合键并且可以使用Map&lt;String, Book&gt; isbnMapMultiMap&lt;String, Book&gt; authorMap MultiMap 对于一对多关系很有用。您的每个查找都只是这些地图上的get(name)

标签: java caching


【解决方案1】:

当您将对象存储在(任何类型的)集合中时,您只存储该对象的引用。所以继续使用多张地图,您将只有一份实际对象的副本。

例如

Map<String,MyBigObject> map1 = new HashMap...
Map<String,MyBigObject> map2 = new HashMap...
MyBigObject mbo = new MyBigObject(...);
map1.put(mbo.getISBN(),mbo);
map2.put(mbo.getAuthor(),mbo);

现在可以通过任一地图访问单个对象 mbo

编辑:如果您担心多个地图的复杂性会使代码复杂化,请编写一个包含所有地图的类MultiMap,并以您想要的任何方式管理它们。您可以使用方法add(MyBigObject...) 将对象插入到所有映射中,使用各种属性访问器来设置正确的键,然后查找方法,例如getByAuthor(...)getByISBN(...),以及您需要的任何其他方法。隐藏简单统一交互背后的所有复杂性。

【讨论】:

  • 我知道它的同一个参考存储在多个地图中。我只是担心创建 N 个地图来以不同的方式存储同一个对象。我想知道是否有任何其他设计方法可以使查找有效并将其存储为单一统一的方式。
  • 谢谢你,这就是我要做的。
  • 最好使用像 Guava Multimap 这样的东西来通过像作者这样的非唯一键来索引书籍,以透明地处理同一个键的多个值。但是,是的,为每个索引使用不同的映射是有意义的,并且试图将所有内容强制到一个映射中不会有任何帮助(并且可能只会意味着更多的哈希冲突)。
猜你喜欢
  • 2018-01-03
  • 2011-01-31
  • 2015-03-10
  • 1970-01-01
  • 2015-05-27
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多