2012-02-16 56 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>>()); 
相關問題