我在Java上使用一个较大(数百万)的hashmap,实际上以10.000.000的容量和0.75的负载系数构建,用于缓存一些值

由于缓存值随着时间而变得毫无用处(不再访问),但是在途中,我无法在其性能开始降低时完全清空该缓存的途径。我该如何决定何时做事?

例如,当它达到7500万个元素时,我应该将100万个容量和.75倒入吗?因为我尝试了各种阈值值,但我想拥有一个分析值。

我已经测试了以下事实:当它完全饱满后,它是一种提高性能(在擦除后首先2-3算法迭代只是填充它,然后它开始运行的速度比擦拭之前的速度要快得多)

编辑:其他信息

哈希图的键和浮点很长。它包含内容的缓存相关性,因为它是我想缓存它们的标签矢量的点产物(以提高性能)。

因此,基本上我要做的是计算 long 键使用2个内容的哈希码:

static private long computeKey(Object o1, Object o2)
{
    int h1 = o1.hashCode();
    int h2 = o2.hashCode();

    if (h1 < h2)
    {
        int swap = h1;
        h1 = h2;
        h2 = swap;
    }

    return ((long)h1) << 32 | h2;
}

并使用它来检索存储的值。发生的事情是,由于它是一个层次的群集内容,并且不再需要其与其他内容的相关值。这就是为什么我想不时擦除哈希图,以免由于其中的无用值而降级。

用一个 WeakHashMap 当仍然需要时,也将不可预测地消除数据。我无法控制它。

谢谢

有帮助吗?

解决方案

为什么不使用LRU缓存?来自Java的LinkedHashmap文档:

提供了一个特殊的构造函数来创建一个链接的哈希地图,其迭代顺序是最后访问其条目的顺序,从最少访问到最清晰的(访问订单)。这种地图非常适合构建LRU缓存。调用PUT或获得方法会导致对相应条目的访问(假设在调用完成后存在)。 Putall方法在指定地图中为每个映射生成一个条目访问,以指定地图的输入集迭代器提供键值映射的顺序。没有其他方法生成条目访问。特别是,收集视图的操作不会影响背映射的迭代顺序。

因此,基本上,随着地图的大小,每隔一段时间,只需删除迭代器给您的第一个X值即可。

请参阅文档 removeEldestEntry 为您自动完成此操作。

这是证明:

 public static void main(String[] args) {
    class CacheMap extends LinkedHashMap{
      private int maxCapacity;
      public CacheMap(int initialCapacity, int maxCapacity) {
        super(initialCapacity, 0.75f, true);
        this.maxCapacity = maxCapacity;
      }

      @Override
      protected boolean removeEldestEntry(Map.Entry eldest) {
        return size()>maxCapacity;
      }
    }

    int[] popular = {1,2,3,4,5};
    CacheMap myCache = new CacheMap(5, 10);
    for (int i=0; i<100; i++){
      myCache.put(i,i);
      for (int p : popular) {
        myCache.get(p);
      }
    }

    System.out.println(myCache.toString()); 
    //{95=95, 96=96, 97=97, 98=98, 99=99, 1=1, 2=2, 3=3, 4=4, 5=5}
  }

其他提示

你调查了吗? 弱藏图 ?垃圾收集器可以确定何时删除东西,它可能会给您可接受的替代品,而不是自己编码。

本文 有更多有用的信息。

您可能想使用Google Collections' MAPMAKER 制作具有软引用和特定超时的地图。

软引用“由垃圾收集器酌情决定,以响应记忆需求。”

例子:

ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
    .concurrencyLevel(32)
    .softValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeMap();

如果您想将其钥匙像弱的钥匙一样,则可以指定弱者。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top