我为自己编写了一个实用程序,将列表分解为给定大小的批次。我只是想知道是否已经有任何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;
}

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


当前回答

利用网上的各种作弊方法,我找到了这个解决方案:

int[] count = new int[1];
final int CHUNK_SIZE = 500;
Map<Integer, List<Long>> chunkedUsers = users.stream().collect( Collectors.groupingBy( 
    user -> {
        count[0]++;
        return Math.floorDiv( count[0], CHUNK_SIZE );
    } )
);

我们使用count来模拟普通的集合索引。 然后,以代数商作为桶号,将集合元素分组到桶中。 最后一个映射包含作为键的桶号,作为值的桶本身。

然后,您可以轻松地对每个桶执行操作:

chunkedUsers.values().forEach( ... );

其他回答

另一种方法是使用收集器。索引的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]

这里有一个例子:

final AtomicInteger counter = new AtomicInteger();
final int partitionSize=3;
final List<Object> list=new ArrayList<>();
            list.add("A");
            list.add("B");
            list.add("C");
            list.add("D");
            list.add("E");
       
        
final Collection<List<Object>> subLists=list.stream().collect(Collectors.groupingBy
                (it->counter.getAndIncrement() / partitionSize))
                .values();
        System.out.println(subLists);

输入: [a, b, c, d, e]

输出: [a, b, c], [d, e]]

你可以在这里找到例子: https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/

如果你想要生成一个Java-8的批处理流,你可以尝试下面的代码:

public static <T> Stream<List<T>> batches(List<T> source, int length) {
    if (length <= 0)
        throw new IllegalArgumentException("length = " + length);
    int size = source.size();
    if (size <= 0)
        return Stream.empty();
    int fullChunks = (size - 1) / length;
    return IntStream.range(0, fullChunks + 1).mapToObj(
        n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length));
}

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

    System.out.println("By 3:");
    batches(list, 3).forEach(System.out::println);
    
    System.out.println("By 4:");
    batches(list, 4).forEach(System.out::println);
}

输出:

By 3:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10, 11, 12]
[13, 14]
By 4:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14]

如果有人正在寻找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和超级秘密模运算符的解决方案:)

考虑到块的内容/顺序并不重要,这将是最简单的方法。(当为多线程准备东西时,这通常并不重要,例如哪个元素在哪个线程上处理,只需要均匀分布)。

public static <T> List<T>[] chunk(List<T> input, int chunkCount) {
    List<T>[] chunks = new List[chunkCount];

    for (int i = 0; i < chunkCount; i++) {
        chunks[i] = new LinkedList<T>();
    }

    for (int i = 0; i < input.size(); i++) {
        chunks[i % chunkCount].add(input.get(i));
    }

    return chunks;
}

用法:

    List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j");

    List<String>[] chunks = chunk(list, 4);

    for (List<String> chunk : chunks) {
        System.out.println(chunk);
    }

输出:

[a, e, i]
[b, f, j]
[c, g]
[d, h]