Reputation: 17806
I have a list of random size greater than 20k. How can I split them into sublists where each sublist will have equal lengths or equal length + 1(for the odd lists?)?
Since it is random size, implementation should not have any defined size right?
I am currently looking at this template:
public static <T> List<List<T>> split(List<T> list, int size) throws NullPointerException, IllegalArgumentException {
if (list == null) {
throw new NullPointerException("The list parameter is null.");
}
if (size <= 0) {
throw new IllegalArgumentException("The size parameter must be more than 0.");
}
int num = list.size() / size;
int mod = list.size() % size;
List<List<T>> ret = new ArrayList<List<T>>(mod > 0 ? num + 1 : num);
for (int i = 0; i < num; i++) {
ret.add(list.subList(i * size, (i + 1) * size));
}
if (mod > 0) {
ret.add(list.subList(num * size, list.size()));
}
return ret;
}
This one is creating sublists based on known sublist size then creating the X sublists.
The result I need is to pass a LIST and a target sublistSize. So I pass a list with size 26346 records and sublistSize 5. I would end up with 5 sublists. the first four sublist would have 5269 records, and the last(5th) sublist would have 5270 records.
Upvotes: 2
Views: 9901
Reputation: 1
try this for mantaining the order of the main list in the sublists.
public <T> List<List<T>> orderedSplit(List<T> list, int lists) throws NullPointerException, IllegalArgumentException {
if (list == null) {
throw new NullPointerException("La lista es nula.");
}
if (lists <= 0) {
throw new IllegalArgumentException("La lista debe divirse en una cantidad mayor a 0.");
}
if(list.size() < lists){
throw new IllegalArgumentException("El tamaño de la lista no es suficiente para esa distribución.");
}
List<List<T>> result = new ArrayList<List<T>>(lists);
int listsSize = list.size() / lists;
int remainder = list.size() % lists;
int index = 0;
int remainderAccess = 0;
int from = index*listsSize + remainderAccess;
int to = (index+1)*listsSize + remainderAccess;
while(lists > index){
if(remainder != 0){
result.add(list.subList(from, to+1));
remainder--;
remainderAccess++;
}else {
result.add(list.subList(from, to));
}
index++;
from = index*listsSize + remainderAccess;
to = (index+1)*listsSize + remainderAccess;
}
return result;
}
Upvotes: 0
Reputation: 562
This is an improvement for Hamsar's aproch using the sublist
method for optimization.
public static <T> List<List<T>> splitListToSubLists(List<T> parentList, int subListSize) {
List<List<T>> subLists = new ArrayList<List<T>>();
if (subListSize > parentList.size()) {
subLists.add(parentList);
} else {
int remainingElements = parentList.size();
int startIndex = 0;
int endIndex = subListSize;
do {
List<T> subList = parentList.subList(startIndex, endIndex);
subLists.add(subList);
startIndex = endIndex;
if (remainingElements - subListSize >= subListSize) {
endIndex = startIndex + subListSize;
} else {
endIndex = startIndex + remainingElements - subList.size();
}
remainingElements -= subList.size();
} while (remainingElements > 0);
}
return subLists;
}
Upvotes: 1
Reputation: 1
This will split the main list into sublist based on the required size of the sublist .
public List splitListToSubList(List<Object> parentList, int childListSize) {
List<List<Object>> childList = new ArrayList<List<Object>>();
List<Object> tempList = new ArrayList<Object>();
int count = 0;
if (parentList != null) {
for (Object obj : parentList) {
if (count < childListSize) {
count = count + 1;
tempList.add(obj);
} else {
childList.add(tempList);
tempList = new ArrayList<Object>();
tempList.add(obj);
count = 1;
}
}
if (tempList.size() < childListSize) {
childList.add(tempList);
}
}
return childList;
}
}
Upvotes: 0
Reputation: 512
How about this? This will do what you said (if the order of the items is not important), create 'size' sublists, and it will distribute all items to the new lists.
public static <T> List<List<T>> split(List<T> list, int size)
throws NullPointerException, IllegalArgumentException {
if (list == null) {
throw new NullPointerException("The list parameter is null.");
}
if (size <= 0) {
throw new IllegalArgumentException(
"The size parameter must be more than 0.");
}
List<List<T>> result = new ArrayList<List<T>>(size);
for (int i = 0; i < size; i++) {
result.add(new ArrayList<T>());
}
int index = 0;
for (T t : list) {
result.get(index).add(t);
index = (index + 1) % size;
}
return result;
}
Upvotes: 10
Reputation: 10322
If you want to maintain the order of the large list in each of the sub-lists, try the following:
public static <T> List<List<T>> split(List<T> list, int numberOfLists) {
if (list == null) {
throw new NullPointerException("The list parameter is null.");
}
if (numberOfLists <= 0) {
throw new IllegalArgumentException(
"The number of lists parameter must be more than 0.");
}
int sizeOfSubList = list.size() / numberOfLists + 1;
int remainder = list.size() % numberOfLists;
List<List<T>> subLists = new ArrayList<List<T>>(numberOfLists);
// if there is a remainder, let the first sub-lists have one length...
for (int i = 0; i < numberOfLists - remainder; i++) {
subLists.add(list.subList(i*sizeOfSubList, (i+1)*sizeOfSubList));
}
// ... the remaining sub-lists will have -1 size than the first.
sizeOfSubList--;
for (int i = numberOfLists - remainder; i < numberOfLists; i++) {
subLists.add(list.subList(i*sizeOfSubList, (i+1)*sizeOfSubList));
}
return subLists;
}
Upvotes: 0