概要
- 与えられたListを任意の数の要素ごとに複数のListに分割する
- OracleのIN句のように一度に処理できる要素数に上限がある場合に有効
Java 8の場合
Java 8ではストリームAPIを活用しリストを分割する
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CollectionUtils {
public static <T> List<List<T>> chunk(List<T> list, int size) {
if (list == null || list.isEmpty() || size <= 0) {
return Collections.emptyList();
}
int block = list.size() / size + (list.size() % size > 0 ? 1 : 0);
return IntStream.range(0, block)
.boxed()
.map(i -> {
int start = i * size;
int end = Math.min(start + size, list.size());
return list.subList(start, end);
})
.collect(Collectors.toList());
}
}
さらにコンパクトな例 (@natty420 さんより)
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CollectionUtils {
public static <T> List<List<T>> chunk(List<T> list, int size) {
return IntStream.range(0, (int) Math.ceil((double) list.size() / (double) size))
.boxed()
.map(i -> list.stream().skip((long) i * size).limit(size).collect(Collectors.toList()))
.collect(Collectors.toList());
}
}
Java 9以降の場合
Java 9の導入されたStream.iterate
を利用できる
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectionUtils {
public static <T> List<List<T>> chunk(List<T> list, int size) {
return Stream.iterate(0, n -> n + size)
.limit((list.size() + size - 1) / size)
.map(n -> list.subList(n, Math.min(n + size, list.size())))
.collect(Collectors.toList());
}
}
Google Guavaライブラリの使用
Lists.partition
が同等の機能を提供している
import com.google.common.collect.Lists;
import java.util.List;
public class CollectionUtils {
public static <T> List<List<T>> chunk(List<T> list, int size) {
return Lists.partition(list, size);
}
}
テストケース
JUnit
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
public class CollectionUtilsTest {
@Test
void testChunk() {
Assertions.assertEquals(
// Expected
Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9),
Arrays.asList(10)
),
// Actual
CollectionUtils.chunk(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 3)
);
}
}