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 等。这些集合允许在运行时添加、删除和修改元素。然而,需要注意的是,在多线程环境下使用可变集合可能需要额外的同步措施,以确保线程安全性。

   

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