2012-02-16 11 views
41

Tôi gặp sự cố khi nhận một khối mã để chạy đúng cách. Tôi không hoàn toàn chắc chắn mã này làm gì (Tôi đang cố gắng để có được một plugin đó là lỗi thời để làm việc đúng với máy chủ của chúng tôi), tôi chỉ biết mỗi 20 phút nó chạy và ném ra một lỗi. Dưới đây là phần mã mà vấn đề đang xảy ra:UnsupportedOperationException tại 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()); 
} 

}

Các lỗi xảy ra từ dòng 42, đó là:

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

Các lỗi nó ra sẽ xảy ra mỗi 20 phút hai lần với 2 giây ở giữa.

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) 

Cảm ơn bạn đã giúp đỡ.

+0

Bạn đã ghi đè bằng và hashcode trên đối tượng ItemInfo, bởi vì bạn đang thực hiện cuộc gọi containsKey trên hashmap. (itemStockMap.containsKey (item.getInfo())) –

Trả lời

1

Sự cố nằm trong lớp đối tượng danh sách được trả về bằng lệnh gọi get. Nó không ghi đè các phương thức add một cách thích hợp và do đó mã của bạn sẽ sử dụng phương thức trình giữ chỗ được cung cấp bởi AbstractList.

Chúng tôi không thể nói nhiều hơn nếu không biết lớp danh sách là gì và (nếu là mã tùy chỉnh), hãy xem mã nguồn.

103

Bạn đang sử dụng Arrays.asList() để tạo ra các danh sách trong Map đây:

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

Phương pháp này trả về một tổ chức phi resizable List hậu thuẫn của mảng. Từ tài liệu của phương pháp đó:

Trả về danh sách kích thước cố định được hỗ trợ bởi mảng được chỉ định. (Thay đổi để danh sách trả lại "viết thông qua" để mảng.)

Để sử dụng một thay đổi kích thước List (và thực sự sao chép nội dung), sử dụng như sau:

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

Lưu ý: nói chung, khi thấy rằng UnsupportedOperationException đang được ném bởi add, v.v. thường là dấu hiệu cho thấy một số mã đang cố gắng sửa đổi bộ sưu tập không thể thay đổi kích thước hoặc không thể sửa đổi.

Ví dụ: Collections.emptyList hoặc Collections.singletonList (trả về bộ sưu tập không thể sửa đổi) có thể được sử dụng làm tối ưu hóa nhưng vô tình được chuyển vào các phương pháp cố gắng sửa đổi chúng. Vì lý do này, nên thực hiện tốt các phương pháp tạo bản sao bộ sưu tập phòng thủ trước khi sửa đổi chúng (trừ khi khóa học sửa đổi bộ sưu tập là tác dụng phụ dự định của phương pháp) - theo cách đó người gọi được tự do sử dụng thực hiện thu thập phù hợp nhất mà không cần lo lắng về việc liệu nó có cần có thể sửa đổi được.

13

Vấn đề là bạn đang tạo danh sách của mình với Arrays.asList. Mỗi javadoc được cung cấp, danh sách trả về là một Fixed Size, do đó add sẽ không được hỗ trợ. Bọc danh sách trả về trong một hàm tạo bản sao cho arrayList và bạn nên thiết lập.

+0

Xin lỗi tôi thực sự mới ở Java .. Bạn vui lòng giải thích rằng cho một nub? Cảm ơn :) – Erickj92

+0

Câu trả lời của Paul thực sự nói cùng một điều (đánh bại tôi bằng 30 giây ... Tôi đã quá chậm khi gõ trên iPhone của mình). Nhưng trong danh sách ngắn bạn đang đưa vào bản đồ của bạn không thể được mở rộng để thêm không được hỗ trợ. – Charlie

18

Tôi nghĩ rằng tôi đã khắc phục được sự cố của bạn.Arrays.asList(item.getStock()) trả về một danh sách kích thước cố định dựa trên Mảng được truyền cho nó.

Điều này có nghĩa là bạn không thể thêm nhiều yếu tố vào nó.

Thay vào đó bạn nên làm new ArrayList(Arrays.asList(item.getStock())).

Bằng cách này bạn đang tạo danh sách mới mà bạn có thể thêm vào.

+1

Điều nhỏ nhặt kén chọn: kích thước cố định (như mảng), nhưng nó không thay đổi, các yếu tố có thể thay đổi, bạn không thể tăng kích thước :) – Charlie

+0

Được rồi, sau đó là Charlie. Đã chỉnh sửa. – Jivings

3

Danh sách là giao diện và bạn không thể Thêm giá trị trong nó cho đến khi nó là thể hiện của ArrayList (giao diện cần được thực hiện bởi một số lớp)

Ví dụ:

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

Đây Object kiểm tratest2 là hoàn hảo, vì chúng là đối tượng của Lớp ArrayList để có thể thêm
Khi ở trong test3 nó chỉ là trống để bạn không thể thêm phần tử vào đó.

Tôi cũng đang phạm sai lầm tương tự.

Đây là đề xuất sử dụng ArrayList của tôi khi bạn phải thực hiện các thao tác như thêm hoặc xóa, chỉ sử dụng danh sách cho mục đích tham khảo.

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