Java: how can I split an ArrayList in multiple small ArrayLists?

JavaArraylist

Java Problem Overview


How can I split an ArrayList (size=1000) in multiple ArrayLists of the same size (=10) ?

ArrayList<Integer> results;

Java Solutions


Solution 1 - Java

You can use subList(int fromIndex, int toIndex) to get a view of a portion of the original list.

From the API:

> Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.

Example:

List<Integer> numbers = new ArrayList<Integer>(
	Arrays.asList(5,3,1,2,9,5,0,7)
);

List<Integer> head = numbers.subList(0, 4);
List<Integer> tail = numbers.subList(4, 8);
System.out.println(head); // prints "[5, 3, 1, 2]"
System.out.println(tail); // prints "[9, 5, 0, 7]"

Collections.sort(head);
System.out.println(numbers); // prints "[1, 2, 3, 5, 9, 5, 0, 7]"

tail.add(-1);
System.out.println(numbers); // prints "[1, 2, 3, 5, 9, 5, 0, 7, -1]"

If you need these chopped lists to be NOT a view, then simply create a new List from the subList. Here's an example of putting a few of these things together:

// chops a list into non-view sublists of length L
static <T> List<List<T>> chopped(List<T> list, final int L) {
	List<List<T>> parts = new ArrayList<List<T>>();
	final int N = list.size();
	for (int i = 0; i < N; i += L) {
		parts.add(new ArrayList<T>(
			list.subList(i, Math.min(N, i + L)))
		);
	}
	return parts;
}


List<Integer> numbers = Collections.unmodifiableList(
	Arrays.asList(5,3,1,2,9,5,0,7)
);
List<List<Integer>> parts = chopped(numbers, 3);
System.out.println(parts); // prints "[[5, 3, 1], [2, 9, 5], [0, 7]]"
parts.get(0).add(-1);
System.out.println(parts); // prints "[[5, 3, 1, -1], [2, 9, 5], [0, 7]]"
System.out.println(numbers); // prints "[5, 3, 1, 2, 9, 5, 0, 7]" (unmodified!)

Solution 2 - Java

You can add the Guava library to your project and use the Lists.partition method, e.g.

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);

Solution 3 - Java

Apache Commons Collections 4 has a partition method in the ListUtils class. Here’s how it works:

import org.apache.commons.collections4.ListUtils;
...

int targetSize = 100;
List<Integer> largeList = ...
List<List<Integer>> output = ListUtils.partition(largeList, targetSize);

Solution 4 - Java

The answer provided by polygenelubricants splits an array based on given size. I was looking for code that would split an array into a given number of parts. Here is the modification I did to the code:

public static <T>List<List<T>> chopIntoParts( final List<T> ls, final int iParts )
{
	final List<List<T>> lsParts = new ArrayList<List<T>>();
	final int iChunkSize = ls.size() / iParts;
	int iLeftOver = ls.size() % iParts;
	int iTake = iChunkSize;

	for( int i = 0, iT = ls.size(); i < iT; i += iTake )
	{
		if( iLeftOver > 0 )
		{
			iLeftOver--;

			iTake = iChunkSize + 1;
		}
		else
		{
			iTake = iChunkSize;
		}

		lsParts.add( new ArrayList<T>( ls.subList( i, Math.min( iT, i + iTake ) ) ) );
	}

	return lsParts;
}

Hope it helps someone.

Solution 5 - Java

Java 8

We can split a list based on some size or based on a condition.

static Collection<List<Integer>> partitionIntegerListBasedOnSize(List<Integer> inputList, int size) {
        return inputList.stream()
                .collect(Collectors.groupingBy(s -> (s-1)/size))
                .values();
}
static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) {
        final AtomicInteger counter = new AtomicInteger(0);
        return inputList.stream()
                    .collect(Collectors.groupingBy(s -> counter.getAndIncrement()/size))
                    .values();
}
static <T> Collection<List<T>> partitionBasedOnCondition(List<T> inputList, Predicate<T> condition) {
        return inputList.stream().collect(Collectors.partitioningBy(s-> (condition.test(s)))).values();
}

Then we can use them as:

final List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(partitionIntegerListBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 3));  // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
System.out.println(partitionBasedOnCondition(list, i -> i<6));  // [[6, 7, 8, 9, 10], [1, 2, 3, 4, 5]]

Solution 6 - Java

This works for me

/**
* Returns List of the List argument passed to this function with size = chunkSize
* 
* @param largeList input list to be portioned
* @param chunkSize maximum size of each partition
* @param <T> Generic type of the List
* @return A list of Lists which is portioned from the original list 
*/
public static  <T> List<List<T>> chunkList(List<T> list, int chunkSize) {
	if (chunkSize <= 0) {
		throw new IllegalArgumentException("Invalid chunk size: " + chunkSize);
	}
	List<List<T>> chunkList = new ArrayList<>(list.size() / chunkSize);
	for (int i = 0; i < list.size(); i += chunkSize) {
		chunkList.add(list.subList(i, i + chunkSize >= list.size() ? list.size()-1 : i + chunkSize));
	}
	return chunkList;
}

Eg :

List<Integer> stringList = new ArrayList<>();
stringList.add(0);
stringList.add(1);
stringList.add(2);
stringList.add(3);
stringList.add(4);
stringList.add(5);
stringList.add(6);
stringList.add(7);
stringList.add(8);
stringList.add(9);
        
List<List<Integer>> chunkList = getChunkList1(stringList, 2);

Solution 7 - Java

Java8 streams, one expression, no other libraries:

List<String> input = ...
int partitionSize = ...

 Collection<List<String>> partitionedList = IntStream.range(0, input.size())
    .boxed()
        .collect(Collectors.groupingBy(partition -> (partition / partitionSize), Collectors.mapping(elementIndex -> input.get(elementIndex), Collectors.toList())))
            .values();

Tests:

List<String> input = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h" ,"i");

> partitionSize = 1 -> [[a], [b], [c], [d], [e], [f], [g], [h], [I]] > > partitionSize = 2 -> [[a, b], [c, d], [e, f], [g, h], [I]] > > partitionSize = 3 -> [[a, b, c], [d, e, f], [g, h, I]] > > partitionSize = 7 -> [[a, b, c, d, e, f, g], [h, I]] > > partitionSize = 100 -> [[a, b, c, d, e, f, g, h, i]]

Solution 8 - Java

private ArrayList<List<String>> chunkArrayList(ArrayList<String> arrayToChunk, int chunkSize) {
    ArrayList<List<String>> chunkList = new ArrayList<>();
    int guide = arrayToChunk.size();
    int index = 0;
    int tale = chunkSize;
    while (tale < arrayToChunk.size()){
            chunkList.add(arrayToChunk.subList(index, tale));
            guide = guide - chunkSize;
            index = index + chunkSize;
            tale = tale + chunkSize;
    }
    if (guide >0) {
       chunkList.add(arrayToChunk.subList(index, index + guide));
    }
    Log.i("Chunked Array: " , chunkList.toString());
    return chunkList;
}

Example

    ArrayList<String> test = new ArrayList<>();
    for (int i=1; i<=1000; i++){
        test.add(String.valueOf(i));
    }

    chunkArrayList(test,10);

Output

CHUNKED:: [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40], [41, 42, 43, 44, 45, 46, 47, 48, 49, 50], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [61, 62, 63, 64, 65, 66, 67, 68, 69, 70], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80], [81, 82, 83, 84, 85, 86, 87, 88, 89, 90], [91, 92, 93, 94, 95, 96, 97, 98, 99, 100], .........

you will see in your log

Solution 9 - Java

A similar question was discussed here, https://stackoverflow.com/questions/379551/java-split-a-list-into-two-sub-lists

Mainly you can use sublist. More details here : subList

> Returns a view of the portion of this list between fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list...

Solution 10 - Java

I'm guessing that the issue you're having is with naming 100 ArrayLists and populating them. You can create an array of ArrayLists and populate each of those using a loop.

The simplest (read stupidest) way to do this is like this:

ArrayList results = new ArrayList(1000);
    // populate results here
    for (int i = 0; i < 1000; i++) {
        results.add(i);
    }
    ArrayList[] resultGroups = new ArrayList[100];
    // initialize all your small ArrayList groups
    for (int i = 0; i < 100; i++) {
            resultGroups[i] = new ArrayList();
    }
    // put your results into those arrays
    for (int i = 0; i < 1000; i++) {
       resultGroups[i/10].add(results.get(i));
    } 

Solution 11 - Java

Create a new list and add a sublist view of the source list using the addAll() method to create a new sublist

List<T> newList = new ArrayList<T>();
newList.addAll(sourceList.subList(startIndex, endIndex));

Solution 12 - Java

You can use the chunk method from Eclipse Collections:

ArrayList<Integer> list = new ArrayList<>(Interval.oneTo(1000));
RichIterable<RichIterable<Integer>> chunks = Iterate.chunk(list, 10);
Verify.assertSize(100, chunks);

A few examples of the chunk method were included in this DZone article as well.

Note: I am a committer for Eclipse Collections.

Solution 13 - Java

Using the StreamEx library, you can use the StreamEx.ofSubLists(List<T> source, int length) method:

> Returns a new StreamEx which consists of non-overlapping sublists of given source list having the specified length (the last sublist may be shorter).

// Assuming you don't actually care that the lists are of type ArrayList
List<List<Integer>> sublists = StreamEx.ofSubLists(result, 10).toList();

// If you actually want them to be of type ArrayList, per your question
List<List<Integer>> sublists = StreamEx.ofSubLists(result, 10).toCollection(ArrayList::new);

Solution 14 - Java

You can also use FunctionalJava library - there is partition method for List. This lib has its own collection types, you can convert them to java collections back and forth.

import fj.data.List;

java.util.List<String> javaList = Arrays.asList("a", "b", "c", "d" );

List<String> fList = Java.<String>Collection_List().f(javaList);

List<List<String> partitions = fList.partition(2);

Solution 15 - Java

import org.apache.commons.collections4.ListUtils;
ArrayList<Integer> mainList = .............;
List<List<Integer>> multipleLists = ListUtils.partition(mainList,100);
int i=1;
for (List<Integer> indexedList : multipleLists){
  System.out.println("Values in List "+i);
  for (Integer value : indexedList)
    System.out.println(value);
i++;
}

Solution 16 - Java

if you don't want to import the apache commons library try this simple code:

final static int MAX_ELEMENT = 20;

public static void main(final String[] args) {

	final List<String> list = new ArrayList<String>();

	for (int i = 1; i <= 161; i++) {
		list.add(String.valueOf(i));
		System.out.print("," + String.valueOf(i));
	}
	System.out.println("");
	System.out.println("### >>> ");
	final List<List<String>> result = splitList(list, MAX_ELEMENT);

	for (final List<String> entry : result) {
		System.out.println("------------------------");
		for (final String elm : entry) {
			System.out.println(elm);
		}
		System.out.println("------------------------");
	}

}

private static List<List<String>> splitList(final List<String> list, final int maxElement) {

	final List<List<String>> result = new ArrayList<List<String>>();

	final int div = list.size() / maxElement;

	System.out.println(div);

	for (int i = 0; i <= div; i++) {

		final int startIndex = i * maxElement;

		if (startIndex >= list.size()) {
			return result;
		}

		final int endIndex = (i + 1) * maxElement;

		if (endIndex < list.size()) {
			result.add(list.subList(startIndex, endIndex));
		} else {
			result.add(list.subList(startIndex, list.size()));
		}

	}

	return result;
}

Solution 17 - Java

Just to be clear, This still have to be tested more...

public class Splitter {

public static <T> List<List<T>> splitList(List<T> listTobeSplit, int size) {
	List<List<T>> sublists= new LinkedList<>();
	if(listTobeSplit.size()>size) {
	int counter=0;
	boolean lastListadded=false;
	
	List<T> subList=new LinkedList<>();
	
	for(T t: listTobeSplit) {			
		 if (counter==0) {				 
			 subList =new LinkedList<>();
			 subList.add(t);
			 counter++;
			 lastListadded=false;
		 }
		 else if(counter>0 && counter<size-1) {
			 subList.add(t);
			 counter++;
		 }
		 else {
			 lastListadded=true;
			 subList.add(t);
			 sublists.add(subList);
			 counter=0;
		 }				
	}
	if(lastListadded==false)
		sublists.add(subList);		
	}
	else {
		sublists.add(listTobeSplit);
	}
	log.debug("sublists: "+sublists);
	return sublists;
 }
}

Solution 18 - Java

    **Divide a list to lists of n size**

    import java.util.AbstractList;
    import java.util.ArrayList;
    import java.util.List;
    
    public final class PartitionUtil<T> extends AbstractList<List<T>> {
    
        private final List<T> list;
        private final int chunkSize;
    
        private PartitionUtil(List<T> list, int chunkSize) {
            this.list = new ArrayList<>(list);
            this.chunkSize = chunkSize;
        }
    
        public static <T> PartitionUtil<T> ofSize(List<T> list, int chunkSize) {
            return new PartitionUtil<>(list, chunkSize);
        }
    
        @Override
        public List<T> get(int index) {
            int start = index * chunkSize;
            int end = Math.min(start + chunkSize, list.size());
    
            if (start > end) {
                throw new IndexOutOfBoundsException("Index " + index + " is out of the list range <0," + (size() - 1) + ">");
            }
    
            return new ArrayList<>(list.subList(start, end));
        }
    
        @Override
        public int size() {
            return (int) Math.ceil((double) list.size() / (double) chunkSize);
        }
    }





Function call : 
              List<List<String>> containerNumChunks = PartitionUtil.ofSize(list, 999)

more details: https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/

Solution 19 - Java

Java8 streams, one expression, no other libraries (two solutions without creating an unnecessary map):

List<List<Integer>> partitionedList = IntStream.range(0, (list.size()-1)/targetSize+1)
        .mapToObj(i -> list.subList(i*targetSize, Math.min(i*targetSize+targetSize, list.size())))
        .collect(Collectors.toList());

List<List<Integer>> partitionedList2 = IntStream.iterate(0, i -> i < list.size(), i -> i + targetSize)
        .mapToObj(i -> list.subList(i, Math.min(i + targetSize, list.size())))
        .collect(Collectors.toList());

Keep in mind these are sublists, so changes to the original list would also affect these.

If you prefer them not to be sublists, and rather newly created independent lists, they can be modified as such:

List<List<Integer>> partitionedList = IntStream.range(0, (list.size()-1)/targetSize+1)
        .mapToObj(i -> IntStream.range(i*targetSize, Math.min(i*targetSize+targetSize, list.size())).mapToObj(j -> list.get(j)).collect(Collectors.toList()))
        .collect(Collectors.toList());

List<List<Integer>> partitionedList2 = IntStream.iterate(0, i -> i < list.size(), i -> i + targetSize)
        .mapToObj(i -> IntStream.range(i, Math.min(i + targetSize, list.size())).mapToObj(j -> list.get(j)).collect(Collectors.toList()))
        .collect(Collectors.toList());

Solution 20 - Java

You need to know the chunk size by which you're dividing your list. Say you have a list of 108 entries and you need a chunk size of 25. Thus you will end up with 5 lists:

  • 4 having 25 entries each;
  • 1 (the fifth) having 8 elements.

Code:

public static void main(String[] args) {
		
		List<Integer> list = new ArrayList<Integer>();
		for (int i=0; i<108; i++){
			list.add(i);
		}
		int size= list.size();
		int j=0;
				List< List<Integer> > splittedList = new ArrayList<List<Integer>>()  ;
				List<Integer> tempList = new ArrayList<Integer>();
		for(j=0;j<size;j++){
			tempList.add(list.get(j));
		if((j+1)%25==0){
			// chunk of 25 created and clearing tempList
			splittedList.add(tempList);
			tempList = null;
			//intializing it again for new chunk 
			tempList = new ArrayList<Integer>();
		}
		}
		if(size%25!=0){
			//adding the remaining enteries 
			splittedList.add(tempList);
		}
		for (int k=0;k<splittedList.size(); k++){
			//(k+1) because we started from k=0
			System.out.println("Chunk number: "+(k+1)+" has elements = "+splittedList.get(k).size());
		}
	}

Solution 21 - Java

Let's suppose you want the considere the class that split the list into multiple chuncks as a library class.

So let's say the class is called 'shared' and in should be final to be sure it won't be extended.

   import java.util.ArrayList;
   import java.util.Arrays;
   import java.util.List;

public final class Shared {
List<Integer> input;
int portion;

public Shared(int portion, Integer... input) {
	this.setPortion(portion);
	this.setInput(input);
}

public List<List<Integer>> listToChunks() {
	List<List<Integer>> result = new ArrayList<List<Integer>>();
	int size = this.size();
	int startAt = 0;
	int endAt = this.portion;

	while (endAt <= size) {

		result.add(this.input.subList(startAt, endAt));
		startAt = endAt;
		endAt = (size - endAt < this.portion && size - endAt > 0) ? (this.size()) : (endAt + this.portion);
	}

	return result;
}

public int size() {
	return this.input.size();
}

public void setInput(Integer... input) {
	if (input != null && input.length > 0)
		this.input = Arrays.asList(input);
	else
		System.out.println("Error 001 : please enter a valid array of integers.");
}

public void setPortion(int portion) {
	if (portion > 0)
		this.portion = portion;
	else
		System.out.println("Error 002 : please enter a valid positive number.");
}
}

Next, let's try to execute it from another class that hold the public static void main(String... args)

public class exercise {

public static void main(String[] args) {
	Integer[] numbers = {1, 2, 3, 4, 5, 6, 7};
	int portion = 2;
	Shared share = new Shared(portion, numbers);
	System.out.println(share.listToChunks());	
}
}

Now, if you enter an array of integer [1, 2, 3, 4, 5, 6, 7] with a partition of 2. the result will be [[1, 2], [3, 4], [5, 6], [7]]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaneuryzmView Question on Stackoverflow
Solution 1 - JavapolygenelubricantsView Answer on Stackoverflow
Solution 2 - JavaMike QView Answer on Stackoverflow
Solution 3 - JavajohnniebView Answer on Stackoverflow
Solution 4 - JavaLaraView Answer on Stackoverflow
Solution 5 - Javaakhil_mittalView Answer on Stackoverflow
Solution 6 - JavaJ.RView Answer on Stackoverflow
Solution 7 - Javai000174View Answer on Stackoverflow
Solution 8 - Javauser3826696View Answer on Stackoverflow
Solution 9 - JavaIncognitoView Answer on Stackoverflow
Solution 10 - Javaangstrom91View Answer on Stackoverflow
Solution 11 - Javauser688View Answer on Stackoverflow
Solution 12 - JavaDonald RaabView Answer on Stackoverflow
Solution 13 - JavaM. JustinView Answer on Stackoverflow
Solution 14 - JavaMikhail GolubtsovView Answer on Stackoverflow
Solution 15 - JavaRahul PalakurthiView Answer on Stackoverflow
Solution 16 - JavaB.JAAFARView Answer on Stackoverflow
Solution 17 - JavaVikkyView Answer on Stackoverflow
Solution 18 - JavaAkhil SabuView Answer on Stackoverflow
Solution 19 - JavadajavaxView Answer on Stackoverflow
Solution 20 - Javayogesh kumarView Answer on Stackoverflow
Solution 21 - JavaImad ALILATView Answer on Stackoverflow