从HashMap中删除最旧的对象以达到一定的大小?

Ask*_*mov 9 java hashmap java-8 java-stream

我有一个Java中的哈希映射,我需要限制其大小(50000的顺序).但我应该只删除最旧的项目.项的时间戳存储在条目对象的字段中:

Map<String, MyModel> snapshot = new  HashMap<>();
Run Code Online (Sandbox Code Playgroud)

public class MyModel { 
    private ZonedDateTime createdAt;
    // other fields...
}
Run Code Online (Sandbox Code Playgroud)

我还按时间戳顺序将它们插入到地图中.

完成这种删除最旧条目的最有效方法是什么?请注意,时间"阈值"未知,只有Map的最终大小.

Bor*_*der 24

HashMap没有"最古老的",它没有"第一",它没有订单.

LinkedHashMap另一方面,A 就是为此设计的,它在条目之间保持一个双向链表,因此保持它们的插入顺序,它还提供了一种removeEldestEntry方法:

public static void main(final String args[]) throws Exception {
    final int maxSize = 4;
    final LinkedHashMap<String, String> cache = new LinkedHashMap<String, String>() {
        @Override
        protected boolean removeEldestEntry(final Map.Entry eldest) {
            return size() > maxSize;
        }
    };

    cache.put("A", "A");
    System.out.println(cache);
    cache.put("B", "A");
    System.out.println(cache);
    cache.put("C", "A");
    System.out.println(cache);
    cache.put("D", "A");
    System.out.println(cache);
    cache.put("E", "A");
    System.out.println(cache);
    cache.put("F", "A");
    System.out.println(cache);
    cache.put("G", "A");
}
Run Code Online (Sandbox Code Playgroud)

输出:

{A=A}
{A=A, B=A}
{A=A, B=A, C=A}
{A=A, B=A, C=A, D=A}
{B=A, C=A, D=A, E=A}
{C=A, D=A, E=A, F=A}
Run Code Online (Sandbox Code Playgroud)

大健康警告

请注意,此实现不是synchronized.如果多个线程同时访问链接的哈希映射,并且至少有一个线程在结构上修改了映射,那么它必须是synchronized外部的.这通常通过synchronizing自然封装地图的某个对象来实现.如果不存在此类对象,则应使用该Collections.synchronizedMap方法"包装"地图.这最好在创建时完成,以防止意外地不同步访问地图:

Map m = Collections.synchronizedMap(new LinkedHashMap(...));

LinkedHashMap 的JavaDoc