我为自己编写了一个实用程序,将列表分解为给定大小的批次。我只是想知道是否已经有任何apache commons util用于此。

public static <T> List<List<T>> getBatches(List<T> collection,int batchSize){
    int i = 0;
    List<List<T>> batches = new ArrayList<List<T>>();
    while(i<collection.size()){
        int nextInc = Math.min(collection.size()-i,batchSize);
        List<T> batch = collection.subList(i,i+nextInc);
        batches.add(batch);
        i = i + nextInc;
    }

    return batches;
}

请让我知道是否有任何现有的公用事业已经相同。


当前回答

下面的例子演示了一个List的分块:

package de.thomasdarimont.labs;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SplitIntoChunks {

    public static void main(String[] args) {

        List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);

        List<List<Integer>> chunks = chunk(ints, 4);

        System.out.printf("Ints:   %s%n", ints);
        System.out.printf("Chunks: %s%n", chunks);
    }

    public static <T> List<List<T>> chunk(List<T> input, int chunkSize) {

        int inputSize = input.size();
        int chunkCount = (int) Math.ceil(inputSize / (double) chunkSize);

        Map<Integer, List<T>> map = new HashMap<>(chunkCount);
        List<List<T>> chunks = new ArrayList<>(chunkCount);

        for (int i = 0; i < inputSize; i++) {

            map.computeIfAbsent(i / chunkSize, (ignore) -> {

                List<T> chunk = new ArrayList<>();
                chunks.add(chunk);
                return chunk;

            }).add(input.get(i));
        }

        return chunks;
    }
}

输出:

Ints:   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Chunks: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]

其他回答

检查Lists.partition(java.util。List, int) from谷歌Guava

返回列表的连续子列表,每个子列表的大小相同(最终列表可能更小)。例如,将包含[a, b, c, d, e]的列表划分为分区大小为3,将生成[[a, b, c], [d, e]]——一个包含三个和两个元素的两个内部列表的外部列表,所有元素都以原始顺序排列。

如果有人正在寻找Kotlin版本,这里是

list.chunked(size)

or

list.windowed(size)

曾经有一个面试问题,我在下面写了一个=D

fun <T> batch(list: List<T>, limit: Int): List<List<T>> {
    val result = ArrayList<List<T>>()

    var batch = ArrayList<T>()

    for (i in list) {
        batch.add(i)
        if (batch.size == limit) {
            result.add(batch)
            batch = ArrayList()
        }
    }
    if (batch.isNotEmpty()) {
        result.add(batch)
    }
    return result
}

Java 8中的一行代码是:

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

private static <T> Collection<List<T>> partition(List<T> xs, int size) {
    return IntStream.range(0, xs.size())
            .boxed()
            .collect(collectingAndThen(toMap(identity(), xs::get), Map::entrySet))
            .stream()
            .collect(groupingBy(x -> x.getKey() / size, mapping(Map.Entry::getValue, toList())))
            .values();

}

另一种方法是使用收集器。索引的groupingBy,然后将分组索引映射到实际元素:

    final List<Integer> numbers = range(1, 12)
            .boxed()
            .collect(toList());
    System.out.println(numbers);

    final List<List<Integer>> groups = range(0, numbers.size())
            .boxed()
            .collect(groupingBy(index -> index / 4))
            .values()
            .stream()
            .map(indices -> indices
                    .stream()
                    .map(numbers::get)
                    .collect(toList()))
            .collect(toList());
    System.out.println(groups);

输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]

List<T> batch = collection.subList(i,i+nextInc);
->
List<T> batch = collection.subList(i, i = i + nextInc);