Мне нужно что-то подобное, так что это моя реализация. Это позволяет вызывающей стороне указать, какая реализация List должна быть возвращена:
package com.mrojas.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListUtils {
/**
* Splits a list into smaller sublists.
* The original list remains unmodified and changes on the sublists are not propagated to the original list.
*
*
* @param original
* The list to split
* @param maxListSize
* The max amount of element a sublist can hold.
* @param listImplementation
* The implementation of List to be used to create the returned sublists
* @return A list of sublists
* @throws IllegalArgumentException
* if the argument maxListSize is zero or a negative number
* @throws NullPointerException
* if arguments original or listImplementation are null
*/
public static final <T> List<List<T>> split(final List<T> original, final int maxListSize,
final Class<? extends List> listImplementation) {
if (maxListSize <= 0) {
throw new IllegalArgumentException("maxListSize must be greater than zero");
}
final T[] elements = (T[]) original.toArray();
final int maxChunks = (int) Math.ceil(elements.length / (double) maxListSize);
final List<List<T>> lists = new ArrayList<List<T>>(maxChunks);
for (int i = 0; i < maxChunks; i++) {
final int from = i * maxListSize;
final int to = Math.min(from + maxListSize, elements.length);
final T[] range = Arrays.copyOfRange(elements, from, to);
lists.add(createSublist(range, listImplementation));
}
return lists;
}
/**
* Splits a list into smaller sublists. The sublists are of type ArrayList.
* The original list remains unmodified and changes on the sublists are not propagated to the original list.
*
*
* @param original
* The list to split
* @param maxListSize
* The max amount of element a sublist can hold.
* @return A list of sublists
*/
public static final <T> List<List<T>> split(final List<T> original, final int maxListSize) {
return split(original, maxListSize, ArrayList.class);
}
private static <T> List<T> createSublist(final T[] elements, final Class<? extends List> listImplementation) {
List<T> sublist;
final List<T> asList = Arrays.asList(elements);
try {
sublist = listImplementation.newInstance();
sublist.addAll(asList);
} catch (final InstantiationException e) {
sublist = asList;
} catch (final IllegalAccessException e) {
sublist = asList;
}
return sublist;
}
}
И некоторые тестовые случаи:
package com.mrojas.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
public class ListUtilsTest {
@Test
public void evenSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
assertEquals(5, sublists.size());
for (final List<Object> sublist : sublists) {
assertEquals(2, sublist.size());
assertTrue(sublist instanceof LinkedList<?>);
}
}
@Test
public void unevenSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 3, LinkedList.class);
assertEquals(4, sublists.size());
assertEquals(3, sublists.get(0).size());
assertEquals(3, sublists.get(1).size());
assertEquals(3, sublists.get(2).size());
assertEquals(1, sublists.get(3).size());
}
@Test
public void greaterThanSizeSplitTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 20, LinkedList.class);
assertEquals(1, sublists.size());
assertEquals(10, sublists.get(0).size());
}
@Test
public void emptyListSplitTest() {
final List<List<Object>> sublists = ListUtils.split(Collections.emptyList(), 10, LinkedList.class);
assertEquals(0, sublists.size());
}
@Test(expected=IllegalArgumentException.class)
public void negativeChunkSizeTest() {
ListUtils.split(getPopulatedList(5), -10, LinkedList.class);
}
@Test
public void invalidClassTest() {
final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
assertEquals(5, sublists.size());
for (final List<Object> sublist : sublists) {
assertEquals(2, sublist.size());
assertTrue(sublist instanceof LinkedList<?>);
}
}
private List<Object> getPopulatedList(final int size) {
final List<Object> list = new ArrayList<Object>(10);
for (int i = 0; i < 10; i++) {
list.add(new Object());
}
return list;
}
}