You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将对象流分块为指定大小N的列表并持续流转

将Java流分割为固定大小的块

Java标准Stream API本身没提供直接分块的方法,但可以通过自定义收集器、手动拆分或者第三方库实现,给你几个实用方案:

方案一:自定义收集器(流式处理,无需预存全部元素)

自己实现一个收集器,能在流处理过程中直接把元素按固定大小N打包成列表,不用先把整个流存到内存里:

public static <T> Collector<T, ?, Stream<List<T>>> chunked(int chunkSize) {
    return Collector.of(
        ArrayList::new,
        (container, item) -> {
            if (container.isEmpty() || container.get(container.size() - 1).size() == chunkSize) {
                container.add(new ArrayList<>(chunkSize));
            }
            container.get(container.size() - 1).add(item);
        },
        (leftContainer, rightContainer) -> {
            if (!leftContainer.isEmpty()) {
                List<T> lastLeftChunk = leftContainer.get(leftContainer.size() - 1);
                if (lastLeftChunk.size() < chunkSize) {
                    rightContainer.stream().findFirst().ifPresent(firstRightChunk -> {
                        int need = chunkSize - lastLeftChunk.size();
                        lastLeftChunk.addAll(firstRightChunk.subList(0, Math.min(need, firstRightChunk.size())));
                        if (firstRightChunk.size() > need) {
                            leftContainer.add(firstRightChunk.subList(need, firstRightChunk.size()));
                        }
                        leftContainer.addAll(rightContainer.subList(1, rightContainer.size()));
                    });
                } else {
                    leftContainer.addAll(rightContainer);
                }
            } else {
                leftContainer.addAll(rightContainer);
            }
            return leftContainer;
        },
        Collection::stream
    );
}

使用方式:

objectStream
    .collect(chunked(N))
    .peek(list -> {
        // 这里处理每个大小为N(最后一个可能更小)的列表
    })
    .forEach(...);

方案二:迭代器手动分块(简单直接)

如果不想写复杂的收集器,也可以先把流收集到列表,再手动拆分:

List<T> sourceList = objectStream.collect(Collectors.toList());
int chunkSize = N;
for (int i = 0; i < sourceList.size(); i += chunkSize) {
    List<T> chunk = sourceList.subList(i, Math.min(i + chunkSize, sourceList.size()));
    // 处理当前块
}

注意:这种方式需要把整个流的元素先存到内存里,适合元素数量不多的场景,不然会占用过多内存。

方案三:用Guava库快速实现

如果项目里已经引入了Guava,可以直接用它的Lists.partition方法,省得自己写代码:

List<T> sourceList = objectStream.collect(Collectors.toList());
List<List<T>> chunks = Lists.partition(sourceList, N);
chunks.stream()
    .peek(list -> {
        // 处理每个块
    })
    .forEach(...);

和方案二一样,需要先把流元素全部收集到列表中。

内容的提问来源于stack exchange,提问作者Arian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 06:23:17