今天看到同事写的非常有意思的代码,乍一看没看懂,到网上学习了一波这几个的用法才搞懂,都是 Java 8 的新特性。
/**
* 验证给定的单据是否符合给定的状态
* @param ids 单据id列表
* @exception BusinessException : 存在数据状态与给定状态不一致
*/
private void allMatchState(List<Integer> ids, int billState) {
listSpiltOpt(ids, index -> {
List<Integer> subList = ids.stream().skip(index * 200).limit(200).collect(Collectors.toList());
if (entryMapper.countByIdsAndState(subList, billState) != subList.size()) {
throw new BusinessException(CommonExceptionEnum.DATA_REFUSE_OPTIONAL);
}
});
}
/**
* list 分页操作
*/
private void listSpiltOpt(List<Integer> ids, Consumer<? super Integer> action) {
Stream.iterate(0, n -> n + 1).limit(ids.size() / 200 + 1).parallel().forEach(action);
}
接下一段一段来分析:
Stream.iterate(0, n -> n + 1)
生成无限流,从 0 开始,每次递增 1,结果就是 0, 1, 2, 3 …
limit(ids.size() / 200 + 1)
limit
截取流,只保留 ids.size() / 200 + 1
个,假设 ids.size() / 200 + 1
=2,那么结果就是 0, 1
forEach(action)
遍历操作 0, 1
,具体操作逻辑是 action,从参数列表来看 action 是 Consumer<? super Integer>
类型,就是传入一个方法,在 forEach 调用的时候才执行传入的方法。这里把 action 替换成
index -> {
List<Integer> subList = ids.stream().skip(index * 200).limit(200).collect(Collectors.toList());
if (entryMapper.countByIdsAndState(subList, billState) != subList.size()) {
throw new BusinessException(CommonExceptionEnum.DATA_REFUSE_OPTIONAL);
}
}
就比较好理解了。
skip(index * 200)
跳过 index * 200
个元素,这里的 index 就是 forEach 要遍历的 0, 1
,结果就是 0 和 200
skip(index * 200).limit(200)
组合起来用就是先遍历 ids.[0-199]
的元素,再遍历 ids.[200-399]
的元素
Reference