2012-02-16 2 views
41

У меня возникают проблемы с правильной работой блока кода. Я не совсем уверен, ЧТО этот код делает (я пытаюсь получить плагин, который устарел, чтобы нормально работать с нашим сервером), я просто знаю каждые 20 минут, когда он запускается, и выдает ошибку. Вот часть кода, где проблема происходит:UnsupportedOperationException at 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

У вас есть переопределенные равные и hashcode на объекте ItemInfo, потому что вы выполняете вызов containsKey в hashmap. (itemStockMap.containsKey (item.getInfo())) –

ответ

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())) 
); 

Примечание: в целом, при виде, что UnsupportedOperationException бросает add и т. Д., Это обычно указывает на то, что какой-то код пытается изменить неизменяемую или не поддающуюся модификации коллекцию.

Например, Collections.emptyList или Collections.singletonList (которые возвращают немодифицируемые коллекции) могут использоваться как оптимизаторы, но случайно передаются в методы, которые пытаются их модифицировать. По этой причине рекомендуется использовать методы для создания защитных копий коллекций до их модификации (если, конечно, изменение коллекции не является предполагаемым побочным эффектом метода), то вызывающие абоненты могут использовать наиболее подходящую реализацию коллекции, не беспокоясь о том, быть модифицируемым.

13

Проблема в том, что вы создаете свои списки с помощью Arrays.asList. За предоставленный javadoc возвращенный список является фиксированным размером, поэтому добавление будет неподдерживаться. Оберните возвращенный список в конструкторе копирования для arrayList, и вы должны быть установлены.

+0

Извините, что я действительно новичок в Java. Не могли бы вы объяснить, что для нуба? Спасибо :) – Erickj92

+0

Ответ Павла на самом деле говорит то же самое (избили меня на 30 секунд ... Я слишком медленно печатал на своем iPhone). Но, короче, списки, которые вы вкладываете в свою карту, не могут быть расширены, поэтому добавление не поддерживается. – Charlie

18

Я думаю, что я разработал вашу проблему.Arrays.asList(item.getStock()) возвращает фиксированный размерный список на основании переданного ему массива.

Это означает, что вы не можете добавить к нему дополнительные элементы.

Вместо этого вы должны сделать new ArrayList(Arrays.asList(item.getStock())).

Таким образом, вы создаете новый список, который вы можете добавить.

+1

Minor nit picky thing: фиксированный размер (например, массив), но он не является неизменным, элементы могут быть изменены, вы просто не можете увеличить размер :) – Charlie

+0

Хорошо, тогда Чарли. Ред. – Jivings

3

Список является интерфейс, и вы не можете добавить значение в нем до тех пор, пока экземпляр 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>>()); 
Смежные вопросы