List集合分页操作

代码实现

在实际业务代码中有时在刷数据时需要对集合List进行分批操作,故此总结记录一下:

for (int i = 0; i < batchList.size(); i += SmsCommonConstants.EduPushVariable.BATCH_NUM) {
int end = i + SmsCommonConstants.EduPushVariable.BATCH_NUM;
      if(end > batchList.size()) {
          end = batchList.size();
      }
      List<SmsBatch> copy = batchList.subList(i, end);

      if(CollectionUtils.isNotEmpty(copy)){
          initDataMapper.insertBatch(copy);

          List<String> batchNos = copy.stream().map(m -> m.getBatchNo()).collect(Collectors.toList());
          updateBatchData(batchNos);
      }
  }

为什么阿里巴巴要求谨慎使用ArrayList中的subList方法

关于集合类,《阿里巴巴Java开发手册》中其实还有另外一个规定:
在这里插入图片描述
为什么会有这个建议呢?我们来看看源码就一目了然了

在这里插入图片描述
subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段、可以理解为截取一个集合中的部分元素,他的返回值也是一个List。

如果我们改动下代码,将subList的返回值强转成ArrayList试一下:

public static void main(String[] args) {
    List<String> names = new ArrayList<String>() {{
        add("Hollis");
        add("hollischuang");
        add("H");
    }};

    ArrayList subList = (ArrayList) names.subList(0, 1);
    System.out.println(subList);
}

以上代码将抛出异常:

Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList

不只是强转成ArrayList会报错,强转成LinkedList、Vector等List的实现类同样也都会报错。

那么,为什么会发生这样的报错呢?我们接下来深入分析一下。

底层原理

首先我么来看一下subList方法返回的是什么,JDK源码里面是这样描述的:

Returns a view of the portion of this list between the specified

也就是说subList 返回是一个视图,那么什么叫做视图呢?

看源码可以看出来这个方法返回了一个SubList,这个类是ArrayList中的一个内部类。

SubList这个类中单独定义了set、get、size、add、remove等方法。

当我们调用subList方法的时候,会通过调用SubList的构造函数创建一个SubList,那么看下这个构造函数做了哪些事情:
在这里插入图片描述
可以看到,这个构造函数中把原来的List以及该List中的部分属性直接赋值给自己的一些属性了。

也就是说,SubList并没有重新创建一个List,而是直接引用了原有的List(返回了父类的视图),只是指定了一下他要使用的元素的范围而已(从fromIndex(包含),到toIndex(不包含))。

所以,为什么不能讲subList方法得到的集合直接转换成ArrayList呢?因为SubList只是ArrayList的内部类,他们之间并没有继承关系,故无法直接进行强制类型转换。

  • 当我们尝试通过set方法,改变subList中某个元素的值得时候,我们发现,原来的那个List中对应元素的值也发生了改变。

  • 同理,如果我们使用同样的方法,对sourceList中的某个元素进行修改,那么subList中对应的值也会发生改变

  • 我们尝试对subList的结构进行改变,即向其追加元素,那么得到的结果是sourceList的结构也同样发生了改变

  • 我们尝试对sourceList的结构进行改变,即向其追加元素,结果发现抛出了ConcurrentModificationException。

在这里插入图片描述

发布了36 篇原创文章 · 获赞 4 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/weixin_41205148/article/details/97773362