项目中使用Java中List.subList()的注意事项

2024-07-17 1158阅读

使用介绍

在Java中,subList是List接口的一个方法,用于获取原始列表的子列表

方法的声明如下

List subList(int fromIndex, int toIndex);
  • fromIndex:起始索引(包括)
  • toIndex:结束索引(不包括)
    List list = new Arraylist();
    List subList = list.subList(0, 5);
    

    返回的子列表是原始列表的一个视图,对子列表的修改会反映在原始列表上,反之亦然。

    例如,下面的语句从列表中移除了元素的范围:

    list.subList(from, to).clear();
    

    下面是一个简单的例子:

    List originalList = new ArrayList(Arrays.asList("A", "B", "C", "D", "E"));
    List subList = originalList.subList(1, 4);
    System.out.println("subList = " + subList); // 子列表包括索引 1,2,3  输出:[B, C, D]
    System.out.println("originalList = " + originalList); // 输出:[A, B, C, D, E]
    subList.add("F");
    System.out.println("subList = " + subList); // 输出: [B, C, D, F]
    System.out.println("originalList = " + originalList);// 输出:[A, B, C, D, F, E] 因为通过subList视图对索引为4的位置添加了一个F
    originalList.add("G");
    // 调用subList()后,如果再对原list进行操作同时对subList()也进行操作(打印、添加、清除),都会报错ConcurrentModificationException,因为这会修改视图的结构
    // subList.add("H") java.util.ConcurrentModificationException
    // System.out.println(subList);  java.util.ConcurrentModificationException
    System.out.println("originalList = " + originalList); // 输出:[A, B, C, D, F, E, G]
    originalList.subList(1, 2).clear();
    System.out.println("originalList = " + originalList); // 输出: [A, C, D, F, E, G] 因为通过视图对索引为1的数据进行了清除

    注意事项

    • ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException 异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.

      说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

      • 在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、 删除均会产生 ConcurrentModificationException 异常。
      • 索引范围: fromIndex 至 toIndex 是左闭右开的范围,即包括 fromIndex 处的元素,但不包括 toIndex 处的元素。
      • 修改原列表: 对子列表的修改会反映在原列表上,反之亦然。这是因为子列表实际上是原列表的一个视图。
      • 不支持结构性修改: 在子列表的视图上不支持对原列表的结构性修改(例如插入、删除元素),否则会抛出ConcurrentModificationException异常。结构性修改是指改变原列表的大小或者使其元素的数量发生变化的操作。
      • 子列表可以增、删、改,但是原列表不支持,理由同上
      • subList()返回的不是List!是Sublist,不是原来的类型
         public List subList(int fromIndex, int toIndex) {
                return (this instanceof RandomAccess ?
                        new RandomAccessSubList(this, fromIndex, toIndex) :
                        new SubList(this, fromIndex, toIndex));
            }
            声明:
            class SubList extends AbstractList{}
        
        •  LinkedList并没有覆盖这个方法.ArryList自己覆盖了这个方法,返回的是java.util.ArrayList.SubList

          public List subList(int fromIndex, int toIndex) {
              subListRangeCheck(fromIndex, toIndex, size);
              return new SubList(this, 0, fromIndex, toIndex);
          }
          声明:
          private class SubList extends AbstractList implements RandomAccess {}
          

          项目中使用Java中List.subList()的注意事项

          看来ArryList处处体现出RandomAccess接口的特性——支持随机访问。

          • java.util.AbstractList.clear()方法就是subList的clear方法
            public void clear() {
                removeRange(0, size());
            }
            ...
            // ArrayList的覆盖
            public void clear() {
                modCount++;
             
                // clear to let GC do its work
                for (int i = 0; i  
            

            项目实战

            大家可以看一下我的慢查询优化实战文章

            在最开始分页慢查询优化没有得到较好的解决方案时,我的操作是直接获取到全部数据的List,然后对List进行截取,达到分页的效果,这是相关的代码

            public static  IPage listToPage(List list, Integer current, Integer size){
                    IPage iPage = new Page(current,size);
                    iPage.setTotal(list.size());
                    int startIndex = (int)((current - 1)*size);
                    if(null == list || list.isEmpty() || startIndex > list.size()){
                        iPage.setRecords(new ArrayList());
                    }
                    else {
                        int toIndex = (int)(current*size);
                        iPage.setRecords(list.subList(startIndex,toIndex > list.size() ? list.size() : toIndex));
                    }
                    return iPage;
                }

            大家可以看到,我对List是只截取不操作的,也就不会出现bug

            注意!subList是返回一个镜像而不是新示例,用了得保证原来的list不能更改!

            over

            参考

            Java中List的subList()方法及使用注意事项_list sublist-CSDN博客

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]