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
,並且沒有重寫 remove
、add
等方法,在這些方法上直接拋出 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"); // 不再拋出異常
可變集合
相反,可變集合是可以進行修改操作的集合。常見的可變集合包括 ArrayList
、LinkedList
等。這些集合允許在運行時添加、刪除和修改元素。然而,需要注意的是,在多線程環境下使用可變集合可能需要額外的同步措施,以確保線程安全性。