带有 removeEldestEntry 的 Java LinkedHashMap 导致 java.lang.NullPointerException

标签 java dictionary get linkedhashmap lru

错误看起来像这样

Exception in thread "Thread-1" java.lang.NullPointerException
    at java.util.LinkedHashMap$Entry.remove(LinkedHashMap.java:332)
    at java.util.LinkedHashMap$Entry.recordAccess(LinkedHashMap.java:356)
    at java.util.LinkedHashMap.get(LinkedHashMap.java:304)
    at Server.getLastFinishedCommands(Server.java:9086)
    at Server.processPacket(Server.java:484)
    at PacketWorker.run(PacketWorker.java:34)
    at java.lang.Thread.run(Thread.java:744)

getLastFinishedCommands 中我使用

   public List<CCommand> getLastFinishedCommands(UserProfile player) {
        List<CCommand> returnList = new ArrayList<CCommand>();

        if(!finishedCommands.containsKey(player.myWebsitecmd-1)) {
            getSavedState(player);
            return null;
        }

        try { //<-- added this try/catch so it doesn't happen again.
            //Get commands.
            CCommand cmd;
            long i;
            long startIndex = player.myWebsitecmd;
            long endIndex = startIndex+LIMIT_COMMANDS;

            for(i = startIndex; i <= endIndex; i++) {
                cmd = finishedCommands.get(i);   //<-- this is line 9086
                if(cmd == null) {
                    return returnList;
                }
                returnList.add(cmd);
            }
        } catch(Exception e) {} //<-- added this try/catch so it doesn't happen again.
        return returnList;
    }

我想制作一个自动删除旧条目的 map ,所以我使用了这个片段

public static <K, V> Map<K, V> createLRUMap(final int maxEntries) {
    return new LinkedHashMap<K, V>(maxEntries*3/2, 0.7f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > maxEntries;
        }
    };
}

是这样用的

public static int final MAX_COMMANDS_QUEUE = 5000;
public Map<Long, CCommand> finishedCommands = createLRUMap(MAX_COMMANDS_QUEUE);

显然,这是某种 CocurrentModifcationException,在与多个线程一起使用时会发生。但是为什么它会在内部崩溃,有人知道我如何将其与 CocurrentHashMap 一起使用吗?我试图解决这个问题,而不是仅仅在整个 getLastFinishedCommands 函数周围放置一个 try/catch。

我想要一个能够清除旧垃圾但仍保留至少 5000 个键/值条目的 Map。

最佳答案

根据堆栈跟踪,我假设代码试图从索引中删除其项目已被另一个线程删除的值。这使得它在访问 null 引用的属性时抛出 NPE。也许,你应该尝试同步集合

来自LinkedHashMap的文档

Note that this implementation is not synchronized. If multiple threads access a linked hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:

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

关于带有 removeEldestEntry 的 Java LinkedHashMap 导致 java.lang.NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22778981/

相关文章:

java - 我在 Java 中遇到了一些递归问题

java - 使用 Ant 生成逗号分隔的文件列表

java - Main 方法无法编译找不到符号来创建对象

json - 将 json 数据更改为 Angular 2 中的 Typescript 接口(interface)对象

php - 使用保存在 session 中的 Url 变量预填充 Woocommerce 结帐字段

php - 具有获取值的表单

java - 如何使用bulkUpdate批量删除

JSON数据: A_Geo: "MULTIPOINT ((121.5831587 24.9971109))" need to be parsed into dictionary

android - api.ai - 禁止 GET/INTENTS 查询 -

c++ - 是否有类似 map 的容器的实现,以实数作为键,并且可以通过键范围检索一组对象?