List集合分组——subList(from,to)

这是一个简单的问题,list集合分组可能会有许多方式,比如循环遍历分组,这样的分组方式会经过多次判断,性能比较低。

首先说说为什么要分组,如果数据小就没有必要了,在处理大数据时,list中可能存储了很多数据,造成很大的内存开销,你为了减轻系统负担,建议对list进行分组操作,并说清除不需要的数据

现在发现List.java中有个类似于字符串截取(subString)的方法subList(int fromIndex,int toIndex),其中参数fromIndex、toIndex分别代表截取的起始下标和终止下标(不包括),源码如下:

List接口中的声明:

 List subList(int fromIndex, int toIndex);

ArrayList中的实现:

 public List subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

 static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size)
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
    }


    private class SubList extends AbstractList implements RandomAccess {
        private final AbstractList parent;
        private final int parentOffset;
        private final int offset;
        int size;

 SubList(AbstractList parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        }

}

显然可以看到subList方法返回的是一个SubList类型,而该类中又有一个parent的引用,由此可知,这种方式获得的子list其实是list集合自身某一指定部分的映射,实际上并没有物理结构(空间复杂度就会降低,节省了空间),这里jdk文档中有解释如下:

Returns a view of the portion of this list between the specified(返回一个list的部分视图)
     * fromIndex, inclusive, and toIndex, exclusive.  (If
     * fromIndex and toIndex are equal, the returned list is
     * empty.)  The returned list is backed by this list, so non-structural(
返回的list是由自身的list支持,所以在返回list中的非结构化的改变会映射到自身的list中
     * changes in the returned list are reflected in this list, and vice-versa.
     * The returned list supports all of the optional list operations supported
     * by this list.

文档中说的很清楚了,返回的list依赖于自身的list,所以对返回的list进行改变就意味着对自身list进行改变(这是subList方法的一个坑

之前看过几篇文章中说过,使用subString可能会造成OOM(out of memory),我对此的理解是:如果subString使用过于频繁,比如使用10w次,因为每次操作会占用很小的内存空间(用于存放parent引用),以至于会被jvm忽略,那么10w次之后内存空间占用就不小了,很可能造成oom(这个地方我没有尝试过,只是个人理解)

那么处理list中的数据之后,如果list中的部分数据已经不需要,可以使用clear()清除:

如果list.subList(from,to).clear();则原来list中from到to的数据就会删除,因此list的长度大小也会改变,可以节省内存开销

 

 

 

你可能感兴趣的:(List)