UnsupportedOperationException at java.util.AbstractList.add

2022-08-31 10:52:57

我在获取代码块正常运行时遇到问题。我不完全确定这段代码的作用(我试图让一个过时的插件与我们的服务器一起正常工作),我只知道它每20分钟运行一次并抛出一个错误。下面是发生问题的代码部分:

public class DynamicThread extends Thread {
private LocalShops plugin = null;


public DynamicThread(ThreadGroup tgroup, String tname, LocalShops plugin) {
    super(tgroup, tname);
    this.plugin = plugin;
}

public void run() {
    Map<ItemInfo, List<Integer>> itemStockMap = Collections.synchronizedMap(new HashMap<ItemInfo, List<Integer>>());

    //Dump all the shop stock data into the map.
    for ( Shop shop : plugin.getShopManager().getAllShops() ) {
        for ( InventoryItem item : shop.getItems() ) {
            if (itemStockMap.containsKey(item.getInfo()))
                itemStockMap.get(item.getInfo()).add(item.getStock()); //Where error happens
            else
                itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));     
        }
    }
    for(ItemInfo item : itemStockMap.keySet()) {
        List<Integer> stockList = GenericFunctions.limitOutliers(itemStockMap.get(item));
        //remove the map before re-adding it
        if (DynamicManager.getPriceAdjMap().containsKey(item)) 
            DynamicManager.getPriceAdjMap().remove(item);

        //Get the overall stock change for a given item and then calculate the adjustment given the volatility
        int deltaStock = GenericFunctions.getSum(stockList) - Config.getGlobalBaseStock();
        DynamicManager.getPriceAdjMap().put(item, GenericFunctions.getAdjustment(Config.getGlobalVolatility(), deltaStock)); 
    }

    Bukkit.getServer().getScheduler().callSyncMethod(plugin, plugin.getShopManager().updateSigns());
}

}

错误发生在第 42 行,即:

                itemStockMap.get(item.getInfo()).add(item.getStock());

它输出的错误每 20 分钟发生两次,中间间隔 2 秒。

2012-02-16 16:53:25 [INFO] Launch Dynamic Thread
2012-02-16 16:53:25 [SEVERE] Exception in thread "dynamic" 
2012-02-16 16:53:25 [SEVERE] java.lang.UnsupportedOperationException
2012-02-16 16:53:25 [SEVERE] at java.util.AbstractList.add(AbstractList.java:131)
2012-02-16 16:53:25 [SEVERE] at java.util.AbstractList.add(AbstractList.java:91)
2012-02-16 16:53:25 [SEVERE] at       com.milkbukkit.localshops.threads.DynamicThread.run(DynamicThread.java:42)

2012-02-16 16:53:27 [INFO] Launch Dynamic Thread
2012-02-16 16:53:27 [SEVERE] Exception in thread "dynamic" 
2012-02-16 16:53:27 [SEVERE] java.lang.UnsupportedOperationException
2012-02-16 16:53:27 [SEVERE] at java.util.AbstractList.add(AbstractList.java:131)
2012-02-16 16:53:27 [SEVERE] at java.util.AbstractList.add(AbstractList.java:91)
2012-02-16 16:53:27 [SEVERE] at     com.milkbukkit.localshops.threads.DynamicThread.run(DynamicThread.java:42)

提前感谢您的任何帮助。


答案 1

您正在使用 Arrays.asList() 在以下位置创建列表:Map

itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));  

此方法返回由数组支持的不可调整大小。从该方法的文档:List

返回由指定数组支持的固定大小的列表。(对返回列表的更改“直写”到数组。

要使用可调整大小(并实际复制内容),请使用以下命令:List

itemStockMap.put(
        item.getInfo(),
        new ArrayList<Integer>(Arrays.asList(item.getStock()))
); 

注意:通常,当看到 由 等抛出时,通常表示某些代码正在尝试修改不可调整大小或不可修改的集合。UnsupportedOperationExceptionadd

例如,或(返回不可修改的集合)可能用作优化,但意外地传递到尝试修改它们的方法中。出于这个原因,方法在修改集合之前制作集合的防御性副本是一种很好的做法(当然,除非修改集合是方法的预期副作用) - 这样调用方就可以自由使用最合适的集合实现,而不必担心它是否需要可修改。Collections.emptyListCollections.singletonList


答案 2

我想我已经解决了你的问题。 根据传递给它的数组返回固定大小的列表Arrays.asList(item.getStock())

这意味着您无法向其添加更多元素。

相反,您应该这样做。new ArrayList(Arrays.asList(item.getStock()))

这样,您就可以创建一个可以添加到的新列表。