【问题标题】:Is there concurrent & self-expiring & ordered hash map in javajava中是否存在并发&自过期&有序哈希映射
【发布时间】:2023-03-21 03:41:01
【问题描述】:

我正在使用来自 google guava 的 ConcurrentHashMap(通过 MapMaker),但没有订购该实现。 google guava 中有ConcurrentSkipListMap,但该结构不会过期。

有什么结构可以两者兼得吗?

【问题讨论】:

    标签: java map guava


    【解决方案1】:

    我会使用ConcurrentSkipListMap 并定期迭代地图以清除过期的东西。由于跳过列表是无限的,这会导致内存泄漏的可能性,当驱逐线程无法赶上时,但实际上这似乎非常非常不可能,除非你做一些极端的事情。我也做过类似的事情我没有想使用后台线程:

    static AtomicInteger cnt = new AtomicInteger();
    
    Val put(K key, V val){
        //Do the usual stuff
        if(cnt.getAndIncrement() % 100 == 0){
            //iterate map and evict stuff
        }
    }
    

    if(cnt.getAndIncrement() % 100 == 0) 可能是一个“聪明的优化”,所以也许你可以像 matt b 建议的那样每次迭代和驱逐。

    哦,当你这样做时,只有一个警告......当时间戳重合时,一定要打破不同实体之间的平等:

    class Entity implaments Comparable<Entity>{
        static AtomicInteger SEQ = new AtomicInteger();
        int id = SEQ.getAndIncrement();
        long timeStamp = System.currentTimeMillis();
    
        int compareTo(Entity other){
            // compare by timestamp
            // If timestamps are equal, don't just return 0 yet!!
            // Compare by id and return 0 ONLY IF the id equals.
            // Otherwise entities disappear from your ordered map and 
            // it's really annoying to debug.
    }
    

    【讨论】:

    • 我使用 UUID 作为键,我认为我可以使用 0 :)
    • 顺便说一句,我使用地图的全部原因是 UUID。我可以将多个事件推送到多个流(我正在寻找的所需结构),并且我希望能够通过 UUID 从不同的流中进行快速查询。如果我要使用一些 LinkedList,我将不得不迭代所有活动流以在 List 项中找到 UUID,但使用地图我可以快速对一堆流进行查询,并快速获取来自同一来源的事件。
    • @kodisha:哦,所以你不按时间戳排序地图?出于好奇,您为什么要按 UUID 排序地图?
    • 是的,我按时间戳排序,但时间戳不是关键,关键是 UUID。时间戳是存储在地图中的对象的属性。
    • @kodisha:我明白了。只是很好奇您将如何使用按 UUID 排序的地图(按字母顺序或我认为的顺序?)...
    【解决方案2】:

    扩展 java.util.LinkedHashMap 并覆盖 removeEldestEntry() 以执行您希望它执行的任何操作。

    【讨论】:

      【解决方案3】:

      听起来您有非常具体和不寻常的要求。您可能必须自己编写。

      【讨论】:

      • 我基本上想要做的是有时间限制的结构。例如,我希望拥有将数据流保持 60 秒,然后自动过期的结构。排序是至关重要的功能,因为我需要绘制传入事件。现在我正在存储时间戳,并在通过 API 将它们打印回来之前在列表中对值进行排序。
      • 是的,你必须自己做。
      • 关键细节是传入事件的时间戳是否不是单调递增的,因为如果是这样,您将能够使用列表。
      【解决方案4】:

      如果你有一个有序的地图(我假设排序是基于时间戳的),那么无论何时你从地图中添加或获取项目,你都可以简单地从地图中排序最小的值扫描到当前时间戳 - 60 秒,并删除任何不足之处。 Map 的有序属性意味着您无需在每次操作时扫描完整列表。

      【讨论】:

      • 不,这意味着排序是时间戳。目前尚不清楚情况是否如此。地图中项目的顺序很可能不是时间戳顺序。
      【解决方案5】:

      为什么不只使用两个有序映射?一个以时间戳为键,用于查找过期事件。另一个由 UUID 键入,用于查找事件。移除过期事件时,使用事件的 UUID 从第二个地图中移除。

      【讨论】:

        【解决方案6】:

        听起来你想要一个并发过期地图的有序视图。您可以从ForwardingMap 构建一个

        【讨论】:

          【解决方案7】:

          很难找到好的过期地图实现。除了番石榴,你可以看看ExpiringMap。换入排序的地图实现以满足您的需求应该相当简单。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多