web-dev-qa-db-ja.com

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回、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)

助けてくれてありがとう。

56
Erickj92

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.emptyListまたはCollections.singletonList(変更不可能なコレクションを返す)は最適化として使用できますが、誤ってそれらを変更しようとするメソッドに渡されます。このため、メソッドを変更する前にコレクションの防御コピーを作成することをお勧めします(もちろん、コレクションの変更がメソッドの意図する副作用でない限り)-呼び出し元は、必要かどうかを心配することなく、最も適切なコレクション実装を自由に使用できます変更可能です。

137
Paul Bellora

私はあなたの問題を解決したと思います。 Arrays.asList(item.getStock())は、渡された配列に基づいて固定サイズリストを返します。

これは、これ以上要素を追加できないことを意味します。

代わりに、new ArrayList(Arrays.asList(item.getStock()))を実行する必要があります。

このようにして、追加できる新しいリストを作成しています。

25
Jivings

問題は、 Arrays.asList でリストを作成していることです。提供されるjavadocによると、返されるリストは固定サイズであるため、追加はサポートされません。返されたリストをarrayListのコピーコンストラクターでラップすると、設定されます。

13
Charlie

リストはインターフェイスであり、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 classのオブジェクトであるため、完全であるため、追加が可能です
testでは、リストは空なのでリストに要素を追加できません。

私も同じ間違いをしていました。

追加または削除などの操作を行う必要がある場合は、ArrayListを使用してください。

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

問題は、get呼び出しによって返されるリストオブジェクトのクラスにあります。 addメソッドを適切にオーバーライドしないため、コードはAbstractListによって提供されるプレースホルダーメソッドを使用しています。

リストクラスが何であるかを知らずに、そして(カスタムコードの場合)ソースコードを確認せずに言えることはこれ以上ありません。

1
Stephen C

私の場合、私は使用していた:

List<File> removeFilesList= Collections.emptyList();

file arraylistを抽象化しました。代わりに使用:

List<File> removeFilesList= new ArrayList<>();

そして、エラーが修正されました。

0