How to Split a List in Apex without using a For Loop

Author: Bruce Tollefson Published: January 16, 2022; Modified: May 12, 2022
computer_chip

The List class in APEX does not have a native method to split a list, such as a java subList or Javascript slice. The brute force way would be to loop through the list and either remove the records that are not wanted or create a new list and add the values to the list. However, loops are expensive and all that is needed to is split the list at some index. Below will go through an overloaded method with multiple signature returns that is splitting a list in Apex without having to loop through a list.

Splitting a List<Integer>

The below method will take a List of Integers and split it based on the index value of where the split should occur:

public static List<Integer> splitList(List<Integer> intList, Integer startSlicePoint) { checkSize(intList.size(), startSlicePoint); String listStr = String.join(intList,';');//will need to change if List has ';' in it List<String> intListStr = listStr.split(';',startSlicePoint); return (List<Integer>)JSON.deserialize(JSON.serialize(intListStr[startSlicePoint-1].split(';')), List<Integer>.class); }

First the above will check to see if the size of the list being input is greater than the index value(the code for that will be shown later). After joining the list into a string with a separator as ‘;'(the separator doesn’t matter). The string will need to be split using the separator from the join and the index point. This will create a string list from the joined string up to the slice point number. The last index of the string will be a grouping string with the remainder of the list as a string. Then split the string again by the separator, serialize the list from the split(sterilization is needed to create a specific structure for deserializing), and deserialize the string to create a list of integers.

Splitting a List<String>

The below method will take a List of Strings and split it based on the index value of where the split should occur:

public static List<String> splitList(List<String> strList, Integer startSlicePoint) { checkSize(strList.size(), startSlicePoint); String listStr = String.join(strList,';');//will need to change if List has ';' in it List<String> strListStr = listStr.split(';',startSlicePoint); return (List<String>)JSON.deserialize(JSON.serialize(strListStr[startSlicePoint-1].split(';')), List<String>.class); }

The above is very similar to the integer method aside from changing the class from List<Integer> to List<String>.

Splitting a List<Object>

The below method will take a List of Objects and split it based on the index value of where the split should occur:

public static List<Object> splitList(List<Object> objList, Integer startSlicePoint) { checkSize(objList.size(), startSlicePoint); String listStr = String.join(objList,';');//will need to change if List has ';' in it List<String> objListStr = listStr.split(';',startSlicePoint); return (List<Object>)JSON.deserializeUntyped(JSON.serialize(objListStr[startSlicePoint-1].split(';'))); }

The above is very similar to the other 2 methods however if you try to deserialize an Object list the following error will occur: System.JSONException: Apex Type unsupported in JSON: Object. Instead, the deserialization method changed to deserializeUntyped().

CheckSize

The below is a common check method in all of the different method types to check and make sure the size of the list if greater than the index. If not it will throw an error otherwise there would be an index out of bounds error.

private static void checkSize(Integer integer1, Integer integer2){ if(integer1 < integer2) throw new ListSlicerException('The List size: '+integer1+' has to be greater than '+integer2); } public class ListSlicerException extends Exception{}

Splitting a List<sObject>

The best was saved for last, the below method type will go through how to split an sObject list in Apex without going through a for loop and return a split list of sObjects.

public static List<sObject> splitList(List<sObject> sObjList, Integer startSlicePoint) { checkSize(sObjList.size(), startSlicePoint); String sObjectListStr = JSON.serialize(sObjList); String sObjSplit = JSON.serialize(sObjectListStr.split('\\},\\{',startSlicePoint)); String sObjReplace = sObjSplit.replace('\\',''); return (List<sObject>)JSON.deserialize(sObjReplace.substring(2,sObjReplace.length()-2).replace('""', '"').replace('"{','{').replace('}"','}'), List<sObject>.class); }

The is a lot more that was is needed for to split an sObject list. First what needs to be understood is what the deserialization method needs in order to return a List<sObject>. This is best understood by creating an sObject in developer console or VSC and outputting the serialization string. Ex.:

List<Account> actList = new List<Account>(); Account act1 = new Account(name='Test', industry = 'Pharmacy'); Account act2 = new Account(name='Test2', industry = 'Pharmacy'); Account act3 = new Account(name='Test3', industry = 'Pharmacy'); actList.add(act1); actList.add(act2); actList.add(act3); system.debug(JSON.serializePretty(actList));

The key is to use JSON.serializePretty() instead of JSON.serialize() as the latter will not show you the exact formation underneath (try both and you will see what I mean). The return will look something like so:

'[ { "attributes" : { "type" : "Account" }, "Name" : "Test", "Industry" : "Pharmacy" }, { "attributes" : { "type" : "Account" }, "Name" : "Test2", "Industry" : "Pharmacy" }, { "attributes" : { "type" : "Account" }, "Name" : "Test3", "Industry" : "Pharmacy" } ]'

This is exactly what the string needs to look like when it is ready to deserialize. Unfortunately when we join and split the list into strings the “attributes” : {“type” : “Account”} key value pair is lost, the ‘{}’ are escaped and a few other things occur in the string. Unlike the other methods this time we serialize the list and split on a different set of separators. Then the string needs to be cleaned up and ends up replacing several different patterns in order for the string to be in the same format as the one above.

Here is the Github repo for splitting a list in apex without a for loop.

Leave a Reply

Your email address will not be published. Required fields are marked *