【问题标题】:Efficient way to prune HashMap修剪HashMap的有效方法
【发布时间】:2010-12-06 16:28:45
【问题描述】:

我正在用 Java 创建享元,我想确保我不会创建太大的地图。有没有更有效的方法来修剪地图?我没有看到任何可以自动执行此操作的属性(例如最大大小的构造函数),所以我在代码中执行此操作。

这是我所拥有的,它非常基本,但我想确保没有更好的方法:

private static void prune() {
    Iterator<Entry<Integer, Integer[]>> iterator =  seeds.entrySet().iterator();
    int removed = 0;
    while(iterator.hasNext()|| removed == pruneLength) {
        iterator.next();
        iterator.remove();
        removed++;
    }
}

【问题讨论】:

  • 您的意思是要避免使用具有广泛键的地图还是?
  • 为什么不使用iterator.remove()?它反映在地图上。
  • 我想限制这张地图随时间的增长。我不应该经常达到这个限制......
  • 在迭代时不要使用Iterator 并删除(或添加)活动列表中的元素 - 这会导致迭代器出现未指定的行为。请改用iterator.remove() 方法。 (参见download.oracle.com/javase/6/docs/api/java/util/Map.html))
  • 对我来说看起来不太安全...

标签: java hashmap pruning


【解决方案1】:

LinkedHashMap 可以用作 LRU 缓存。

Map<Integer, Integer[]> map = createLRUMap(128);

public static <K, V> Map<K, V> createLRUMap(final int maxSize) {
    return new LinkedHashMap<K,V>(maxSize, 1, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
            return size() > maxSize;
        }
    };
}

【讨论】:

  • 我正在测试这个。
  • 它使用内置/测试代码,并且非常简单地实现了LRU。
  • Opps,小错误,因为它会在匹配最大尺寸而不是大于最大尺寸时删除最后一个元素。
【解决方案2】:

GuavaMapMaker 在其最新版本中有此功能(在主干上)。它应该在 r08 中,虽然我不知道它什么时候出来。

ConcurrentMap<Integer, Integer[]> seeds = new MapMaker()
     .maximumSize(maxSize)
     .makeMap();

请注意,这是一个线程安全的并发映射,这似乎很重要,具体取决于您使用它的方式。

【讨论】:

  • // MapMaker, MapMaker, make me a map...
【解决方案3】:

您是否考虑过使用缓存,例如EhCache?它们实现了映射,并且可以声明式地设置大小、值存储在磁盘上后的限制等。

【讨论】:

  • 这是一个很小的项目,我认为没有必要将它带到 EhCache 级别。不过感谢您的建议……我会在以后的项目中记住这一点。
  • ehcache 是一个非常不错的库。但是,如果可能的话,我总是更喜欢从简单的开始。
【解决方案4】:

数据库世界的一种可能性是拥有两个(或可能更多的地图)。查找使用这两个地图。只写一个。当正在写入的内容达到容量时,替换/清除只读映射并切换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-28
    • 2020-02-25
    • 2017-12-25
    • 2015-04-29
    • 1970-01-01
    • 2014-02-22
    • 2015-04-07
    • 1970-01-01
    相关资源
    最近更新 更多