Java 何时丢弃hashmap内容以避免性能下降?

Java 何时丢弃hashmap内容以避免性能下降?,java,performance,hashmap,load-factor,Java,Performance,Hashmap,Load Factor,我正在用一个大型(百万)hashmap在Java上工作,这个hashmap实际上是以10.000.000的容量和.75的负载因子构建的,它用于缓存一些值 由于缓存的值随着时间的推移变得无用(不再被访问),但我无法删除无用的值,同时我希望在性能开始下降时完全清空缓存。我怎样才能决定什么时候做这件事好呢 例如,有1000万个容量和0.75,当它达到750万个元素时,我应该清空它吗?因为我尝试了各种阈值,但我想要一个分析值 我已经测试过这样一个事实,即在它满的时候使用emp可以提高性能(擦除后的第一个

我正在用一个大型(百万)hashmap在Java上工作,这个hashmap实际上是以10.000.000的容量和.75的负载因子构建的,它用于缓存一些值

由于缓存的值随着时间的推移变得无用(不再被访问),但我无法删除无用的值,同时我希望在性能开始下降时完全清空缓存。我怎样才能决定什么时候做这件事好呢

例如,有1000万个容量和0.75,当它达到750万个元素时,我应该清空它吗?因为我尝试了各种阈值,但我想要一个分析值

我已经测试过这样一个事实,即在它满的时候使用emp可以提高性能(擦除后的第一个2-3次算法迭代只是将其填充回来,然后它开始比擦除前运行得更快)

编辑:其他信息

hashmap具有长键和浮点值。它包含内容的缓存关联,因为它是我想要缓存它们(以提高性能)的标记向量的点积

所以基本上我要做的是使用两个内容的hashcodes计算一个
long
键:

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;
}
static private long computeKey(对象o1,对象o2)
{
int h1=o1.hashCode();
int h2=o2.hashCode();
if(h1
有更多有用的信息。

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

提供了一个特殊的构造函数来 创建一个链接的哈希映射,其顺序为 迭代的顺序是 上次访问的条目来自 最近访问次数最少的 最近(访问顺序)。此 这种地图非常适合建筑 LRU缓存。调用put或get 方法导致访问 相应的条目(假定为 在调用后存在 完成)。putAll方法 为每个用户生成一个条目访问权限 在指定的映射中,在 设置键值映射的顺序 由指定映射的条目提供 设置迭代器。没有其他方法 生成条目访问。在 特别是在 集合视图不影响 背衬贴图的迭代顺序

所以基本上,每隔一段时间,当你的地图变得太大时,只需删除迭代器给你的第一个x值

要自动完成此操作,请参阅
removeeldestentiry
的文档

下面是演示以下内容的代码:

 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}
  }
publicstaticvoidmain(字符串[]args){
类CacheMap扩展了LinkedHashMap{
专用int最大容量;
公共缓存映射(int initialCapacity,int maxCapacity){
超级(初始容量,0.75f,真实值);
this.maxCapacity=maxCapacity;
}
@凌驾
受保护的布尔重构(Map.Entry最早){
返回大小()>最大容量;
}
}
int[]popular={1,2,3,4,5};
CacheMap myCache=新的CacheMap(5,10);

对于(int i=0;i您可能希望使用Google Collections’来制作带有软引用和特定超时的映射

“软引用”由垃圾收集器根据内存需求自行清除

例如:

ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
    .concurrencyLevel(32)
    .softValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeMap();
ConcurrentMap cacheMap=newmapmaker()
.1级(32)
.softValues()
.有效期(30,时间单位:分钟)
.makeMap();

如果你想让weakKeys的键像WeakHashMap中的键一样工作,你也可以指定weakKeys。

@Jack:你的hashmaps中有什么?我在Java中使用的是巨大的hashmap,但键(有时还有值)可以用原语表示。因此,Trove集合(你可能想查看)比默认的java集合要好多了。然后我第二个Z5H的回答:听起来好像你想要LRU hashmap。我编辑了这个问题,提供了更多的细节。根据杰克给出的最新信息,我认为你的LRU解决方案比我的弱HasHMAP好得多。所以我删除了我的,并用了你的。