UnsupportedOperationException java.util.AbstractList.add
我遇到问题需要一段代码才能正常运行。我不完全确定这段代码是干什么的(我试图得到一个已经过时的插件,可以正常使用我们的服务器),我只知道它每运行20分钟就会抛出一个错误。这里有一个代码,其中的问题是发生的部分:}UnsupportedOperationException java.util.AbstractList.add
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)
在此先感谢您的帮助。
问题出在get
调用返回的列表对象的类中。它不会正确覆盖add
方法,因此您的代码使用AbstractList
提供的占位符方法。
如果不知道列表类是什么,并且(如果它是自定义代码)看到源代码,我们可以说没有太多的东西可以说。
您使用Arrays.asList()
创造在这里Map
名单:
itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));
这个方法返回由数组支持的不可调整大小的List
。从该方法的文档:
返回由指定数组支持的固定大小列表。 (更改 返回列表“写”到数组。)
为了使用一个可调整大小的List
(实际上是复制的内容),使用以下命令:
itemStockMap.put(
item.getInfo(),
new ArrayList<Integer>(Arrays.asList(item.getStock()))
);
注意:一般来说,当看到UnsupportedOperationException
被add
等抛出时,它通常表示某些代码试图修改不可调整大小或不可修改的集合。
例如,Collections.emptyList
或Collections.singletonList
(返回不可修改的集合)可能被用作优化,但意外地被传递到试图修改它们的方法中。由于这个原因,在修改它们之前对方法做出防御性副本是一种很好的做法(除非修改方法是一种方法的预期副作用) - 这样调用方可以*地使用最合适的收集实现,而不用担心它是否需要可修改。
List是接口,你不能将它添加值,直到它的ArrayList实例(接口应该由一些类实现)
例如:
List<Integer> test = new ArrayList<>();
test.add(new Integer(2));
ArrayList<Integer> test2 = new ArrayList<>();
test2.add(new Integer(2));
List<Integer> test3 = Collections.EMPTY_LIST;
test3.add(new Integer(2));
这里对象测试和test2是完美的,因为它们是的对象ArrayList类因此可以添加
而在test3它只是空的列表,所以你不能在其中添加元素。
我也在做同样的错误。
这是我的建议使用ArrayList当你必须做像添加或删除操作,使用列表仅用于参考目的。
Map<ItemInfo, ArrayList<Integer>> itemStockMap = Collections.synchronizedMap(new HashMap<ItemInfo, ArrayList<Integer>>());
您是否重写了ItemInfo对象上的equals和hashcode,因为您正在对hashmap执行containsKey调用。 (itemStockMap.containsKey(item.getInfo())) – 2012-02-16 23:07:16