平常我们需要对一个大的list进行分批操作,一般使用Iterators#partition和paddedPartition方法(也可以使用Lists#partition)具体使用方式:
List<Order> result = Lists.newArrayListWithCapacity(orders.size());
for (List<String> orderList : Iterables.paddedPartition(orders, DEFAULT_MAX_SIZE)) {
//doSometime.....
}
使用paddedPartition会出现一个问题,当最后一批的数据小于DEFAULT_MAX_SIZE时候,会把剩下的数据填充为null,比如
list = [1,2,3,4,5] -------paddedPartition(list,3)-------->[[1,2],[3,4],[5,null]]
我们看下源码
public static <T> UnmodifiableIterator<List<T>> paddedPartition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, true);
}
private static <T> UnmodifiableIterator<List<T>> partitionImpl(
final Iterator<T> iterator, final int size, final boolean pad) {
checkNotNull(iterator);
checkArgument(size > 0);
return new UnmodifiableIterator<List<T>>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public List<T> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Object[] array = new Object[size];
int count = 0;
for (; count < size && iterator.hasNext(); count++) {
array[count] = iterator.next();
}
for (int i = count; i < size; i++) {
array[i] = null; // 这里重点,在这一步会判断下最后一页的剩余数据设置为null
}
@SuppressWarnings("unchecked") // we only put Ts in it
List<T> list = Collections.unmodifiableList((List<T>) Arrays.asList(array));
// 这里会根据pad 判断是否返回list 还是 重新生成一个list
return (pad || count == size) ? list : list.subList(0, count);
}
};
}
我们再看下他的孪生的方法
public static <T> UnmodifiableIterator<List<T>> partition(Iterator<T> iterator, int size) {
return partitionImpl(iterator, size, false);
}
都是使用的同一个方法 一个pad(填充)设置为true,一个设置的false
另外,上面我们提到过Lists#partition的方法,他的做法是构建两个新的类实现的
public static <T> List<List<T>> partition(List<T> list, int size) {
checkNotNull(list);
checkArgument(size > 0);
return (list instanceof RandomAccess)
? new RandomAccessPartition<T>(list, size)
: new Partition<T>(list, size);
}