首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以按插入/访问顺序遍历番石榴缓存?

是否可以按插入/访问顺序遍历番石榴缓存?
EN

Stack Overflow用户
提问于 2014-02-23 10:01:27
回答 2查看 5.6K关注 0票数 5

我正在尝试使用一个番石榴缓存作为ConcurrentLinkedHashMap的替代品。但是我发现,虽然ConcurrentLinkedHashMap允许我按插入顺序遍历映射,但Guava的asMap()方法并不按任何特定顺序返回元素。我是遗漏了什么,还是这个功能根本不可用?

示例(试图打印键、值和条目):

代码语言:javascript
复制
Cache<Integer, Integer> cache = CacheBuilder.newBuilder().maximumSize(10).initialCapacity(10)
        .expireAfterAccess(10000, TimeUnit.SECONDS).build();

cache.put(1, 1);
cache.put(2, 2);
cache.put(3, 3);
cache.put(4, 4);
cache.put(5, 5);
cache.put(6, 6);

Iterator<Integer> iter1 = cache.asMap().keySet().iterator();

System.out.println("Keys");
while (iter1.hasNext())
    System.out.println(iter1.next());

System.out.println("Values");
Iterator<Integer> iter2 = cache.asMap().values().iterator();

while (iter2.hasNext())
    System.out.println(iter2.next());

System.out.println("Entries");
Iterator<Entry<Integer, Integer>> iter3 = cache.asMap().entrySet().iterator();

while (iter3.hasNext()) {
    Entry<Integer,Integer> entry = iter3.next();
    System.out.println(entry.getKey() + " " + entry.getValue());
}

指纹:

代码语言:javascript
复制
Keys
2
6
1
4
3
5
Values
2
6
1
4
3
5
Entries
2 2
6 6
1 1
4 4
3 3
5 5
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-07 18:34:24

CacheWriter将允许在显式写入或删除时调用代码。对于加载缓存,您必须在加载器中执行相同的工作。这也是在条目的锁下执行的,所以您可以假设原子性。这将使您可以在不依赖缓存的内部数据结构的情况下维护排序。注意,如果执行有序迭代时所做的工作很昂贵,您可能希望在锁内复制它,然后在外部执行该工作,以避免阻止缓存写入。

代码语言:javascript
复制
LinkedHashMap<K, V> orderedMap = new LinkedHashMap<>();
LoadingCache<K, V> cache = Caffeine.newBuilder()
    .writer(new CacheWriter<K, V>() {
      public void write(K key, V value) {
        synchronized (orderedMap) {
          orderedMap.put(key, value);
        }
      }
      public void delete(K key, V value, RemovalCause cause) {
        if (cause == RemovalCause.REPLACED) {
          return;
        }
        synchronized (orderedMap) {
          orderedMap.remove(key);
        }
      }
    })
    .maximumSize(1_000)
    .build(key -> {
        V value = ...
        synchronized (orderedMap) {
          orderedMap.put(key, value);
        }
        return value;
    });

cache.put(key1, value); // calls writer under lock
cache.get(key2); // calls loader under lock; not writer
cache.invalidate(key1); // calls writer under lock
cache.policy().eviction().get().setMaximum(0); // calls writer under lock

synchronized (orderedMap) {
  for (K key : orderedMap.keySet()) {
    // do work, but blocks writes!
  }
}
票数 2
EN

Stack Overflow用户

发布于 2014-02-24 09:57:13

(回答我自己的问题)

似乎fge的答案是正确的,番石榴缓存不能按插入顺序迭代。作为解决办法,我使用了前面提到的ConcurrentLinkedHashMap,它的特性不那么丰富,但允许有序的迭代。

我仍然希望得到番石榴团队成员的正式答复,因为这似乎表明ConcurrentLinkedHashMap没有完全集成到番石榴中(与ConcurrentLinkedHashMap文档相反)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21966778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档