J'ai des problèmes pour faire fonctionner correctement un bloc de code. Je ne suis pas tout à fait sûr de ce que fait ce code (j'essaie d'obtenir un plugin obsolète pour fonctionner correctement avec notre serveur), je sais juste toutes les 20 minutes qu'il s'exécute et génère une erreur. Voici la section de code où le problème se produit:
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());
}
}
L'erreur se produit à partir de la ligne 42, qui est:
itemStockMap.get(item.getInfo()).add(item.getStock());
L'erreur qu'il génère se produit toutes les 20 minutes deux fois avec 2 secondes entre les deux.
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)
Merci d'avance pour votre aide.
Vous utilisez Arrays.asList()
pour créer les listes dans le Map
ici:
itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));
Cette méthode renvoie un List
non redimensionnable soutenu par le tableau. De la documentation de cette méthode:
Renvoie une liste de taille fixe soutenue par le tableau spécifié. (Modifications de la liste renvoyée "écriture directe" dans le tableau.)
Pour utiliser un List
redimensionnable (et en fait copier le contenu), utilisez ce qui suit:
itemStockMap.put(
item.getInfo(),
new ArrayList<Integer>(Arrays.asList(item.getStock()))
);
Remarque: en général, lorsque vous voyez que UnsupportedOperationException
est lancé par add
, etc., c'est généralement une indication que un code essaie de modifier une collection non redimensionnable ou non modifiable.
Par exemple, Collections.emptyList
ou Collections.singletonList
(qui renvoient des collections non modifiables) peut être utilisé comme optimisation mais être accidentellement transmis à des méthodes qui tentent de les modifier. Pour cette raison, il est recommandé que les méthodes fassent des copies défensives des collections avant de les modifier (à moins bien sûr que la modification de la collection soit l'effet secondaire prévu d'une méthode) - de cette façon, les appelants sont libres d'utiliser l'implémentation de collection la plus appropriée sans se soucier de savoir si elle a besoin être modifiable.
Je pense que j'ai résolu votre problème. Arrays.asList(item.getStock())
renvoie un liste de taille fixe basé sur le tableau qui lui est passé.
Cela signifie que vous ne pouvez pas y ajouter d'autres éléments.
Au lieu de cela, vous devez faire new ArrayList(Arrays.asList(item.getStock()))
.
De cette façon, vous créez une nouvelle liste à laquelle vous pouvez ajouter.
Le problème est que vous créez vos listes avec Arrays.asList . Selon le javadoc fourni, la liste renvoyée est une taille fixe, donc l'ajout ne serait pas pris en charge. Enveloppez la liste retournée dans un constructeur de copie pour arrayList et vous devriez être défini.
La liste est Interface et vous ne pouvez pas y ajouter de valeur tant qu'elle n'est pas une instance d'ArrayList (l'interface doit être implémentée par une classe)
Par exemple:
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));
Ici l'objet tester et test2 sont parfaits, car ils font l'objet de classe ArrayList donc l'addition est possible
En test c'est juste une liste vide donc vous ne pouvez pas y ajouter d'élément.
Je faisais aussi la même erreur.
Voici ma suggestion Utilisez ArrayList lorsque vous devez effectuer des opérations comme ajouter ou supprimer, utiliser la liste uniquement à des fins de référence.
Map<ItemInfo, ArrayList<Integer>> itemStockMap = Collections.synchronizedMap(new HashMap<ItemInfo, ArrayList<Integer>>());
Le problème se situe dans la classe de l'objet liste qui est retourné par l'appel get
. Il ne remplace pas les méthodes add
de manière appropriée, et votre code utilise donc la méthode d'espace réservé fournie par AbstractList
.
Il n'y a pas grand-chose de plus à dire sans savoir ce qu'est la classe de liste et (s'il s'agit de code personnalisé) voir le code source.
Dans mon cas, j'avais utilisé:
List<File> removeFilesList= Collections.emptyList();
ce qui a rendu mon arraylist File abstrait. Utilisé à la place:
List<File> removeFilesList= new ArrayList<>();
Et l'erreur a été corrigée.