列表拆分技术详解
按固定数量拆分列表
Google Guava的Lists.partition方法
源码分析
Lists.java
import com.google.common.collect.Lists;
public class ListSplitter {
public static <E> List<List<E>> splitList(List<E> sourceList, int size) {
if (sourceList == null) {
throw new IllegalArgumentException("源列表不能为空");
}
if (size <= 0) {
throw new IllegalArgumentException("分区大小必须大于0");
}
return (sourceList instanceof java.util.RandomAccess) ?
new RandomAccessPartition<>(sourceList, size) : new Partition<>(sourceList, size);
}
private static class Partition<E> extends AbstractList<List<E>> {
private final List<E> list;
private final int partitionSize;
Partition(List<E> list, int partitionSize) {
this.list = list;
this.partitionSize = partitionSize;
}
@Override
public List<E> get(int index) {
int start = index * partitionSize;
int end = Math.min(start + partitionSize, list.size());
return list.subList(start, end);
}
@Override
public int size() {
return (int) Math.ceil((double) list.size() / partitionSize);
}
}
private static class RandomAccessPartition<E> extends Partition<E> implements java.util.RandomAccess {
RandomAccessPartition(List<E> list, int partitionSize) {
super(list, partitionSize);
}
}
}
使用示例
List<Long> numbers = java.util.stream.LongStream.rangeClosed(1, 400).boxed().toList();
List<List<Long>> partitions = ListSplitter.splitList(numbers, 100);
注意事项
- 外层列表不可修改,但可以修改内部元素。
- 子列表与原列表共享数据,修改子列表会影响原列表。
Apache Commons Collections的ListUtils.partition方法
源码分析
ListUtils.java
import org.apache.commons.collections4.ListUtils;
public class ApacheListSplitter {
public static <T> List<List<T>> splitList(List<T> sourceList, int size) {
if (sourceList == null) {
throw new IllegalArgumentException("源列表不能为空");
}
if (size <= 0) {
throw new IllegalArgumentException("分区大小必须大于0");
}
return new Partition<>(sourceList, size);
}
private static class Partition<T> extends AbstractList<List<T>> {
private final List<T> list;
private final int partitionSize;
Partition(List<T> list, int partitionSize) {
this.list = list;
this.partitionSize = partitionSize;
}
@Override
public List<T> get(int index) {
int start = index * partitionSize;
int end = Math.min(start + partitionSize, list.size());
return list.subList(start, end);
}
@Override
public int size() {
return (int) Math.ceil((double) list.size() / partitionSize);
}
}
}
使用示例
List<Long> numbers = java.util.stream.LongStream.rangeClosed(1, 400).boxed().toList();
List<List<Long>> partitions = ApacheListSplitter.splitList(numbers, 100);
注意事项
- 类似于Guava实现,外层列表不可修改。
平均分成N份
Java Stream的方法
使用示例
List<Long> numbers = java.util.stream.LongStream.rangeClosed(1, 400).boxed().toList();
int maxSize = 10;
int limit = (numbers.size() + maxSize - 1) / maxSize;
List<List<Long>> partitions = java.util.stream.Stream.iterate(0, n -> n + 1)
.limit(limit)
.map(a -> numbers.stream().skip(a * maxSize).limit(maxSize).toList())
.toList();
注意事项
- 并行流可能影响顺序,需根据实际情况调整。