Java集合操作:可變集合和不可變集合

Java集合操作:可變集合和不可變集合

   問題產生:java.lang.UnsupportedOperationException

   問題定位:在通過mybatisPlus獲取分頁列表的時候寫了下面這段代碼 

 1 //分頁獲取列表
 2 PageResult<InsuranceBeneficiaryDO> pageList = this.insuranceBeneficiaryDAO.getList(beneficiaryListBO);
 3 
 4 List<InsuranceBeneficiaryDO> insuredList = pageList.getData();
 5 
 6 insuredList.add(0, applicantDO);
 7 
 8 ...
 9 public PageResult<InsuranceBeneficiaryDO> getList(BeneficiaryListBO beneficiaryListBO) {
10     LambdaQueryWrapper<InsuranceBeneficiaryDO> beneficiaryQueryWrapper = new LambdaQueryWrapper<>();
11 
12     beneficiaryQueryWrapper.eq(InsuranceBeneficiaryDO::getCurrentUserId, beneficiaryListBO.getUserId())
13        .eq(InsuranceBeneficiaryDO::getIsApplicant, YesnoEnum.NO.getType())
14        .eq(InsuranceBeneficiaryDO::getIsDelete, YesnoEnum.NO.getType())
15        .like(Objects.nonNull(beneficiaryListBO.getBeneficiaryName()), InsuranceBeneficiaryDO::getBeneficiaryName,beneficiaryListBO.getBeneficiaryName())
16        .orderByDesc(InsuranceBeneficiaryDO::getCreateTime)
17        .orderByDesc(InsuranceBeneficiaryDO::getId);
18 
19     IPage<InsuranceBeneficiaryDO> page = new Page<>(beneficiaryListBO.getCurrentPage(), beneficiaryListBO.getPageSize());
20     IPage<InsuranceBeneficiaryDO> pageData = this.page(page, beneficiaryQueryWrapper);
21 
22     return new PageResult<>(pageData.getRecords(), PageUtil.transformToPaginator(pageData));
23 }

    明明編輯器也沒有提示不能使用add,怎麼會報出這個異常呢?

    通過查閱資料,結合代碼進行分析,原來是對不可變集合進行添加操作,導致的異常。下面是分析過程:

    上面獲取分頁數據,用到了Page類(com.baomidou.mybatisplus.extension.plugins.pagination.Page),它的構造方法如下:

 1     public Page() {
 2         this.records = Collections.emptyList();
 3         this.total = 0L;
 4         this.size = 10L;
 5         this.current = 1L;
 6         this.orders = new ArrayList();
 7         this.optimizeCountSql = true;
 8         this.isSearchCount = true;
 9         this.hitCount = false;
10     }

  下面是Collections(java.util.Collections)中的相關代碼:

 1     public static final <T> List<T> emptyList() {
 2         return (List<T>) EMPTY_LIST;
 3     }
 4 
 5     public static final List EMPTY_LIST = new EmptyList<>();
 6 
 7     //靜態內部類
 8     private static class EmptyList<E> extends AbstractList<E> implements RandomAccess,Serializable {
 9  10         private static final long serialVersionUID = 8842843931221139166L;
11         ...
12     }

   分析:Collections.emptyList()返回的結果實際上是 Collections.EmptyList,是 Collections 類的一個私有靜態內部類,在繼承AbstractList後並沒有實現add()、remove()等方法,所以返回的List不能進行增加和刪除元素操作。

   因此,Collections.emptyList() 返回一個空的、不可修改的 List實例。嘗試對其進行add,remove操作就會throw UnsupportedOperationException。

  

   由於這裏業務需要的是可修改的列表,可以這樣來處理:

   1 List<InsuranceBeneficiaryDO> insuredList = new ArrayList<>(pageList.getData()); 

   說明:java.util.ArrayList在繼承AbstractList後,實現了remove、add等方法,所以是支持這些操作的。

   這裏涉及到知識點:不可變集合和可變集合

   不可變集合

   不可變集合是指一旦創建就不能更改的集合。在 Java 中,常見的不可變集合包括 Collections.unmodifiableList() 返回的列表,以及 Java 9 之後引入的 List.of() 等方法返回的不可變集合。不可變集合的優點在於其線程安全性和對錯誤的防範性。但是,它們的缺點是無法進行修改操作。

   除了上面提到的Collections.emptyList(),還有Arrays.asList()

  Arrays.asList() 是一個用於將數組轉換爲列表的方法。然而,它返回的列表並非來自 java.util.ArrayList,而是來自 Arrays 內部的一個特殊實現。這個實現繼承自 AbstractList,並且沒有重寫 removeadd 等方法,在這些方法上直接拋出 UnsupportedOperationException 異常。

 1 問題示例:
 2 
 3 List<String> myList = Arrays.asList("apple", "orange", "banana");
 4 
 5 myList.add("grape"); // 拋出 UnsupportedOperationException 異常
 6 
 7 
 8 解決方案:
 9 
10 List<String> myList = new ArrayList<>(Arrays.asList("apple", "orange", "banana"));
11 
12 myList.add("grape"); // 不再拋出異常

   可變集合

   相反,可變集合是可以進行修改操作的集合。常見的可變集合包括 ArrayListLinkedList 等。這些集合允許在運行時添加、刪除和修改元素。然而,需要注意的是,在多線程環境下使用可變集合可能需要額外的同步措施,以確保線程安全性。

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章