java.util.AbstractList.add 处的 UnsupportedOperationException

发布于 2025-01-06 13:46:53 字数 2802 浏览 2 评论 0原文

我在让代码块正常运行时遇到问题。我不完全确定这段代码的作用(我正在尝试获取一个过时的插件以便与我们的服务器正常工作),我只知道它每 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 秒。

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)

I'm having issues getting a block of code to run properly. I'm not entirely sure WHAT this code does (I'm trying to get a plugin that's out of date to work properly with our server), I just know every 20 minutes it runs and throws out an error. Here's the section of code where the issue is happening:

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

}

The error happens from line 42, which is:

                itemStockMap.get(item.getInfo()).add(item.getStock());

The error it outputs happens every 20 minutes twice with 2 seconds in between.

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

夏雨凉 2025-01-13 13:46:53

您正在使用 Arrays.asList()Map 中创建列表:

itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));  

此方法返回一个由大批。从该方法的文档中:

返回由指定数组支持的固定大小列表。 (更改为
返回的列表“写入”数组。)

为了使用可调整大小的List(并实际复制内容),请使用以下内容:

itemStockMap.put(
        item.getInfo(),
        new ArrayList<Integer>(Arrays.asList(item.getStock()))
); 

注意:一般来说,当看到 add 等抛出 UnsupportedOperationException 时,这通常表明某些代码正在尝试修改不可调整大小或不可修改的集合。

例如,Collections.emptyListCollections.singletonList(返回不可修改的集合)可能被用作优化,但意外地被传递到尝试修改它们的方法中。因此,方法在修改集合之前制作集合的防御性副本是一种很好的做法(当然,除非修改集合是方法的预期副作用),这样调用者就可以自由地使用最合适的集合实现,而不必担心它是否需要可修改。

You're using Arrays.asList() to create the lists in the Map here:

itemStockMap.put(item.getInfo(), Arrays.asList(item.getStock()));  

This method returns a non-resizable List backed by the array. From that method's documentation:

Returns a fixed-size list backed by the specified array. (Changes to
the returned list "write through" to the array.)

In order to use a resizable List (and actually copy the contents), use the following:

itemStockMap.put(
        item.getInfo(),
        new ArrayList<Integer>(Arrays.asList(item.getStock()))
); 

Note: in general, when seeing that UnsupportedOperationException is being thrown by add, etc. it's typically an indication that some code is trying to modify a non-resizable or unmodifiable collection.

For example, Collections.emptyList or Collections.singletonList (which return unmodifiable collections) may be used as optimizations but accidentally be passed into methods that try to modify them. For this reason it's good practice for methods to make defensive copies of collections before modifying them (unless of course modifying the collection is a method's intended side effect) - that way callers are free to use the most appropriate collection implementation without worrying about whether it needs to be modifiable.

梦里的微风 2025-01-13 13:46:53

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

这意味着您无法向其中添加更多元素。

相反,您应该执行 new ArrayList(Arrays.asList(item.getStock())) 。

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

I think I've worked out your problem. Arrays.asList(item.getStock()) returns a fixed size list based on the Array passed to it.

This means you cannot add more elements to it.

Instead you should do new ArrayList(Arrays.asList(item.getStock())).

This way you are creating a new list that you can add to.

晚雾 2025-01-13 13:46:53

问题是您正在使用 Arrays.asList。根据提供的 javadoc,返回的列表是固定大小的,因此不支持添加。将返回的列表包装在 arrayList 的复制构造函数中,您应该已设置完毕。

The problem is you are creating your lists with Arrays.asList. Per the javadoc provided, the returned list is a Fixed Size, therefore add would be unsupported. Wrap the returned list in a copy constructor for arrayList and you should be set.

独夜无伴 2025-01-13 13:46:53

就我而言,我使用了:

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

这使我的文件数组列表变得抽象。改为使用:

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

错误已修复。

In my case I had used:

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

which made my File arraylist abstract. Used instead:

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

And the error was fixed.

灵芸 2025-01-13 13:46:53

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

这里对象 testtest2 是完美的,因为它们是ArrayList类的对象,所以可以添加
而在test3中它只是空列表,所以你不能在其中添加元素。

我也犯了同样的错误。

这是我的建议,当您必须执行添加或删除等操作时,请使用 ArrayList,使用 List 仅供参考。

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

List is Interface and you can not Add value in it until it is instance of ArrayList(interface should be implemented by some class)

For Example:

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

Here Object test and test2 are perfect, because they are object of ArrayList class so addition is possible
While in test3 it is just empty list so you can not add element in it.

I was also doing the same mistake.

Here is my Suggestion Use ArrayList when you have to do operations like add or remove, Use List only for reference purpose.

 Map<ItemInfo, ArrayList<Integer>> itemStockMap = Collections.synchronizedMap(new HashMap<ItemInfo, ArrayList<Integer>>());
高跟鞋的旋律 2025-01-13 13:46:53

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

如果不知道列表类是什么并且(如果是自定义代码)查看源代码,我们就无话可说。

The problem is in the class of the list object that is returned by the get call. It doesn't override the add methods appropriately, and your code is therefore using the placeholder method provided by AbstractList.

There's not much more we can say without knowing what the list class is, and (if it is custom code) seeing the source code.

木格 2025-01-13 13:46:53

就我而言,使用 java 17 它通过使用 toList() 从流中返回列表来引起;然后向其中添加元素,

private static List<String> getCancelTxs(List<BetTransaction> betTransactions) {
        return betTransactions.stream()
                .filter(betTx -> betTx.getType().equals(BetTransactionType.SOME_THING))
                .map(BetTransaction::getExternalTxId)
                .toList();
    }

然后通过以下方式添加:

List<String> cancelTxs = getCancelTxs(betTransactions);
cancelTxs.add(externalTxId);

我将 toList(); 替换为 .collect(Collectors.toList());
它解决了

in my case,using java 17 it cuased by returning a List from the stream using toList(); then adding elements to it

private static List<String> getCancelTxs(List<BetTransaction> betTransactions) {
        return betTransactions.stream()
                .filter(betTx -> betTx.getType().equals(BetTransactionType.SOME_THING))
                .map(BetTransaction::getExternalTxId)
                .toList();
    }

then adding to it by:

List<String> cancelTxs = getCancelTxs(betTransactions);
cancelTxs.add(externalTxId);

I replaced toList(); with .collect(Collectors.toList());
and it resolved

对岸观火 2025-01-13 13:46:53

出现这个问题是因为 List.of() 和 Collections.singletonList() 都创建不可变列表。这意味着您无法添加、删除或修改这些列表中的元素。以下是每个方法的详细说明:

1 : List.of(actionDetail):

List<ActionDetail> actionDetailList = List.of(actionDetail);

actionDetailList.add(new ActionDetail()); // 抛出 UnsupportedOperationException

2 : Collections.singletonList(actionDetail):

List<ActionDetail> actionDetailList = Collections.singletonList(actionDetail);

actionDetailList.set(0, new ActionDetail()); // 抛出 UnsupportedOperationException

因此,应该使用以下内容来操作元素

List<ActionDetail> actionDetailList = new ArrayList<>();
actionDetailList.add(actionDetail);

The issue arises because both List.of() and Collections.singletonList() create immutable lists. This means you cannot add, remove, or modify elements in these lists. Here's a breakdown of each method:

1 : List.of(actionDetail):

List<ActionDetail> actionDetailList = List.of(actionDetail);

actionDetailList.add(new ActionDetail()); // Throws UnsupportedOperationException

2 : Collections.singletonList(actionDetail):

List<ActionDetail> actionDetailList = Collections.singletonList(actionDetail);

actionDetailList.set(0, new ActionDetail()); // Throws UnsupportedOperationException

Therefore, the following should be used to manipulate the element

List<ActionDetail> actionDetailList = new ArrayList<>();
actionDetailList.add(actionDetail);
要走就滚别墨迹 2025-01-13 13:46:53

我使用 getter 来获取列表,但它返回列表的固定大小,并且您无法添加新元素,因此

您应该这样做

new ArrayList(Arrays.asList(item.getStock()))

I was using a getter to get the list, but it was returning the fixed size of the list and you can't add a new element so,

Instead you should do

new ArrayList(Arrays.asList(item.getStock()))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文