java.util.AbstractList.add的UnsupportedOperationException

我有问题得到一个代码块正确运行。 我不完全确定这个代码是做什么的(我试图得到一个插件已经过时,可以正常使用我们的服务器),我只知道它每运行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) 

在此先感谢您的帮助。

您正在使用Arrays.asList()Map创build列表:

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

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

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

为了使用可resize的List (并实际上复制内容),请使用以下内容:

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

注意:一般来说,在看到UnsupportedOperationExceptionadd等引发时,通常表明某些代码试图修改不可resize或不可修改的集合。

例如, Collections.emptyListCollections.singletonList (返回不可修改的集合)可以被用作优化,但是被意外地传递到试图修改它们的方法中。 由于这个原因,在修改集合之前,对方法进行防御性复制是一种很好的做法(除非修改集合是一种方法的预期副作用),那么调用者可以自由地使用最合适的集合实现,而不用担心是否需要是可以修改的。

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

这意味着你不能添加更多的元素。

相反,你应该做new ArrayList(Arrays.asList(item.getStock()))

这样你就可以创build一个你可以添加到的新列表。

问题是你正在用Arrays.asList创build你的列表。 根据提供的javadoc,返回的列表是一个固定大小,因此add将不被支持。 将返回的列表包装在arrayList的拷贝构造函数中,并且应该被设置。

问题出在get调用返回的列表对象的类中。 它不会正确地重写add方法,因此您的代码使用AbstractList提供的占位符方法。

如果不知道列表类是什么,以及(如果是自定义代码)看到源代码,我们就可以说不多了。

列表是接口,你不能添加值,直到它是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)); 

这里对象testingtesting2是完美的,因为它们是ArrayList类的对象,因此可以添加
而在test3中它只是空的列表,所以你不能在其中添加元素。

我也犯了同样的错误。

这里是我的build议使用ArrayList,当你必须做像添加或删除操作,使用列表只用于参考的目的。

  Map<ItemInfo, ArrayList<Integer>> itemStockMap = Collections.synchronizedMap(new HashMap<ItemInfo, ArrayList<Integer>>());