iCodeLikeImDrunk
iCodeLikeImDrunk

Reputation: 17806

Is there a simple way to split ONE list into X sublists?

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

Answers (5)

user5888751
user5888751

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

Lori
Lori

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

Hamsar
Hamsar

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

user114676
user114676

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

kuporific
kuporific

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

Related Questions