在公司写代码的时候看到老员工用到一个工具类,看不懂作用但大为震撼。据称是我们技术经理写的。不知道有什么用,于是拿去偷偷请教药老,药老看了三分钟,告诉我原来是这么一回事,先上代码:
/** * 集合分割 * @param collection 集合 * @param splitSize 分割条件, eg,1000个元素按照100分隔,则splitSize=100 * @param <T> 元素类型 * @author hult * @return <T> List<Collection> */ public static <T> List<Collection> splitList(Collection<T> collection, int splitSize) { if (collection.isEmpty()) { return Collections.emptyList(); } int splitCount = (collection.size() + splitSize - 1) / splitSize; return Stream.iterate(0, n -> n + 1) .limit(splitCount) .parallel() .map(index -> collection.stream().skip((long)index * splitSize).limit(splitSize).collect(Collectors.toList())) .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); }
首先要明白这个方法到底想干嘛?
假设这样一个场景,用户浏览页面数据,你用了mybatisPlus进行了分页,用户想要得到10条数据,而后端设置的最大请求参数值是5条数据,而用户在前端请求过来的是10个数据。那这10条数据经过这个ComputeUtil.splitList(Collection<T> collection, int splitSize)方法,其实是把这10条数据折叠起来了(为了满足你的设置的最大请求数是5的要求嘛),把一个一维数组变成了二维数组。如下图:
现在是不是有两个list?
用户传过来了0123456789,他想要的数据是这样的,但是我们设置了一个最大值是5,就不允许他一次十条的处理,为什么这么做呢?
药老猜测说可能是为了性能上的考虑,把它拆分开,可能性能上会好一点,并且还可以节省点内存,避免出现内存溢出。
这个方法会返回一个大list,里面装了两个小list,此所谓折叠。这个方法返回的大list,长度为2,元素对象为两个小list,然后每个小list里面的长度都是5
下图为所见部分代码截图:
@Override public List<BusinessUnitExamine> queryByUnitIds(List<String> businessIds) { if (businessIds.isEmpty()) { return new ArrayList<>(); } int maxSize = 1000; if (businessIds.size() < maxSize) { return new LambdaQueryChainWrapper<>(mapper) .in(BusinessUnitExamine::getAssociateId, businessIds) .list(); } return ComputeUtil.splitList(businessIds, maxSize) .stream() .map(childIds -> new LambdaQueryChainWrapper<>(mapper) .in(BusinessUnitExamine::getAssociateId, childIds) .list() ) .flatMap(Collection::stream) .collect(Collectors.toList()); }
里面的childIds是什么意思呢?对于返回的二维数组又做了一个stream流处理,childIds对应每一个list1和list2。这里相当于把一次查询分成了两次查询,然后从数据库里查出来是in在businessUnitExamine.getAssociateId或者是childIds里边。先查在businessUnitExamine.getAssociateId里边再查在childIds里边,最后把查出来的结果反折叠(用flatMap)再转成lit,就是不是又把一个二维数组处理成了一个一维数组?
这样做的好处?
1、提高性能(我一块一块的去处理,总比我一起去处理总要好的)
2、节省内存,避免出现内存溢出(这个为最主要的作用)
为什么说要避免内存溢出呢?
咱们的服务器都是有内存上限的。比如说有一个G的内存,那么我们最多申请用到1024MB的空间。那这样经过工具类去进行分割折叠处理的话,我可以去反复的利用这1024M空间内存,就不用每次一开始就申请全部的1024M空间。
好了,今天的新知就学到这里了,那么,坐在屏幕前的你,学废了吗?