2012-02-16 47 views
41

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

在此先感谢您的帮助。

+0

您是否重写了ItemInfo对象上的equals和hashcode,因为您正在对hashmap执行containsKey调用。 (itemStockMap.containsKey(item.getInfo())) – 2012-02-16 23:07:16

回答

1

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

如果不知道列表类是什么,并且(如果它是自定义代码)看到源代码,我们可以说没有太多的东西可以说。

103

您使用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(返回不可修改的集合)可能被用作优化,但意外地被传递到试图修改它们的方法中。由于这个原因,在修改它们之前对方法做出防御性副本是一种很好的做法(除非修改方法是一种方法的预期副作用) - 这样调用方可以自由地使用最合适的收集实现,而不用担心它是否需要可修改。

13

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

+0

对不起,我真的是Java的新手..你能否解释一下这个问题?谢谢:) – Erickj92 2012-02-16 23:09:22

+0

保罗的答案实际上是说同样的事情(打我30秒...我在我的iPhone上打字太慢)。但简而言之,您要放入地图的列表无法展开,因此不支持添加。 – Charlie 2012-02-16 23:14:03

18

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

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

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

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

+1

未成年人挑剔的事情:它是固定的大小(如数组),但它不是一成不变的,元素可以改变,你只是不能增加大小:) – Charlie 2012-02-16 23:16:47

+0

好吧,然后查理。编辑。 – Jivings 2012-02-16 23:23:56

3

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>>()); 
相关问题