Har*_*ish 127 java collections
我自己写了一个实用程序来将列表分成给定大小的批次.我只是想知道是否已经有任何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;
}
Run Code Online (Sandbox Code Playgroud)
如果已有相同的实用程序,请告诉我.
Tom*_*icz 237
从Google Guava退房: Lists.partition(java.util.List, int)
返回列表的连续子列表,每个列表具有相同的大小(最终列表可能更小).例如,划分包含一个列表
[a, b, c, d, e]以3个收率分区大小[[a, b, c],[d, e]]-包含三个的两个内列表和两个元件,都在原始顺序的外列表.
Tag*_*eev 47
如果您想生成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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
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]
Run Code Online (Sandbox Code Playgroud)
小智 33
这是 Java 8+ 的一个简单解决方案:
public static <T> Collection<List<T>> prepareChunks(List<T> inputList, int chunkSize) {
AtomicInteger counter = new AtomicInteger();
return inputList.stream().collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values();
}
Run Code Online (Sandbox Code Playgroud)
Adr*_*ona 14
另一种方法是使用Collectors.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);
Run Code Online (Sandbox Code Playgroud)
输出:
[1,2,3,4,5,6,7,8,9,10,11]
[[1,2,3,4],[5,6,7,8],[9,10,11]]
小智 14
使用 Apache Commons ListUtils.partition。
org.apache.commons.collections4.ListUtils.partition(final List<T> list, final int size)
Run Code Online (Sandbox Code Playgroud)
小智 9
这里有一个例子:
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);
Run Code Online (Sandbox Code Playgroud)
输入: [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/
小智 7
我想出了这个:
private static <T> List<List<T>> partition(Collection<T> members, int maxSize)
{
List<List<T>> res = new ArrayList<>();
List<T> internal = new ArrayList<>();
for (T member : members)
{
internal.add(member);
if (internal.size() == maxSize)
{
res.add(internal);
internal = new ArrayList<>();
}
}
if (internal.isEmpty() == false)
{
res.add(internal);
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
下面的示例演示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;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Ints: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Chunks: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]
Run Code Online (Sandbox Code Playgroud)
还有另一个问题因与此问题重复而被关闭,但如果您仔细阅读它,就会发现它有细微的不同。因此,如果有人(像我一样)实际上想要将列表拆分为给定数量的几乎相同大小的子列表,请继续阅读。
我只是将这里描述的算法移植到 Java 中。
@Test
public void shouldPartitionListIntoAlmostEquallySizedSublists() {
List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
int numberOfPartitions = 3;
List<List<String>> split = IntStream.range(0, numberOfPartitions).boxed()
.map(i -> list.subList(
partitionOffset(list.size(), numberOfPartitions, i),
partitionOffset(list.size(), numberOfPartitions, i + 1)))
.collect(toList());
assertThat(split, hasSize(numberOfPartitions));
assertEquals(list.size(), split.stream().flatMap(Collection::stream).count());
assertThat(split, hasItems(Arrays.asList("a", "b", "c"), Arrays.asList("d", "e"), Arrays.asList("f", "g")));
}
private static int partitionOffset(int length, int numberOfPartitions, int partitionIndex) {
return partitionIndex * (length / numberOfPartitions) + Math.min(partitionIndex, length % numberOfPartitions);
}
Run Code Online (Sandbox Code Playgroud)
在Java 9,您可以使用IntStream.iterate()与hasNext条件。因此,您可以将方法的代码简化为:
public static <T> List<List<T>> getBatches(List<T> collection, int batchSize) {
return IntStream.iterate(0, i -> i < collection.size(), i -> i + batchSize)
.mapToObj(i -> collection.subList(i, Math.min(i + batchSize, collection.size())))
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
使用{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},结果为getBatches(numbers, 4):
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]
Run Code Online (Sandbox Code Playgroud)