Collections in Apex

In Salesforce Apex, group of data must be store inside collections. There are three main types of collections List, Set, Map. These collections provide powerful tools for working with data in apex. They allows developers to efficiently manage and manipulate data within their application.

Lists

Lis is a ordered collection of same data type elements means, sequence of data matters. As sequence is maintain in list it’s elements are accessible through indices. Lists are similar to arrays in other programming languages. It allows to store duplicate values or elements. Elements of list can be of any type – primitive data types, collections, sObjects, user defined types and apex types. We can create multidimensional list by nesting collections. List contains seven level deep nested collection inside it means, total eight levels.

How to declare a List ?

When we declare list using new keyword. It instantiating a new instance of list class. It allocates memory to our variable and making it available to store elements.

List<Integer> intList; //Declare list but not initialized. Memory not allocated, Does not hold any element.
System.debug(intList);//Print null value

List<String> colorList = new List<String>(); //Declaration and Initialization in a single statement.
System.debug(colorList); //prints empty list

List<String> cityList = new List<String>{'Mumbai','Delhi','Kolkata','Hyderabad'}; //Declaration and Initialization with certain values.
System.debug(cityList); //prints default values.

List<String> numbers = new List<String>{'One','Two',3,'Four'}; //Compile time error: Initial expression of incorrect type.
System.debug(numbers);
USER_DEBUG [2]|DEBUG|null
USER_DEBUG [5]|DEBUG|()
USER_DEBUG [8]|DEBUG|(Mumbai, Delhi, Kolkata, Hyderabad)

General Purpose List Methods

List<String> cityList = new List<String>{'Mumbai','Delhi','Kolkata','Hyderabad'};
System.debug(cityList);

List<String> copyCityList = new List<String>(cityList); //Create a copy of list and assign it to copyCityList list variable
System.debug(copyCityList);

System.debug(cityList.equals(copyCityList)); //returns true if elements are equal and are in same order.

List<String> cities = cityList.clone(); //create a duplicate copy of list.
System.debug(cities);
System.debug(cityList.equals(cities));

cityList.add('Pune'); //Add element to end of the list.
System.debug(cityList);
cityList.add(2,'Chennai');//Add element to specific index. 
System.debug(cityList);
//Throw List Index out of bound Exception.
cityList.add(7,'Banglore');//It allows to enter element to specific index but index should be less than size of list. 

System.debug(cityList[0]);
System.debug(cityList.get(0)); //returns list element stored at given index.
System.debug(cityList.contains('Chennai'));//returns true if specified element present in list else return false.
System.debug(cityList.indexOf('Delhi'));
USER_DEBUG [2]|DEBUG|(Mumbai, Delhi, Kolkata, Hyderabad)
USER_DEBUG [5]|DEBUG|(Mumbai, Delhi, Kolkata, Hyderabad)
USER_DEBUG [7]|DEBUG|true
USER_DEBUG [10]|DEBUG|(Mumbai, Delhi, Kolkata, Hyderabad)
USER_DEBUG [11]|DEBUG|true
USER_DEBUG [14]|DEBUG|(Mumbai, Delhi, Kolkata, Hyderabad, Pune)
USER_DEBUG [16]|DEBUG|(Mumbai, Delhi, Chennai, Kolkata, Hyderabad, Pune)
USER_DEBUG [20]|DEBUG|Mumbai
USER_DEBUG [21]|DEBUG|Mumbai
USER_DEBUG [22]|DEBUG|true
USER_DEBUG [23]|DEBUG|1

Please refer List Class , for more information and list of supported methods.

Sets

A Set is a collection type that stores unique elements. It is an unordered collection of elements hence, we cannot access set elements through specific index. Element of set can be of primitive types, collections, sObjects, user-defined types, and built-in Apex types.

How to declare a Set ?

Set<String> names;
System.debug(names);

Set<String> companies = new Set<String>();
System.debug(companies);

Set<String> cities = new Set<String>{'Mumbai','New York','Tokyo'};
System.debug(cities);
USER_DEBUG [2]|DEBUG|null
USER_DEBUG [5]|DEBUG|{}
USER_DEBUG [8]|DEBUG|{Mumbai, New York, Tokyo}

General Purpose Set Methods

List<Integer> marks = new List<Integer>{80,85,90,95,90};
Set<Integer> copyOfMarks = new Set<Integer>(marks);
System.debug(copyOfMarks); //duplicate elements not allow.
System.debug(copyOfMarks.containsAll(marks)); //return true if set contain all elements from specified list or set.

Set<String> courseCodes = new Set<String>();
courseCodes.add('EC302'); //Add element to set if not present already
courseCodes.add('EC301');
System.debug(courseCodes);

System.debug(courseCodes.size()); //returns size of set
System.debug(copyOfMarks.isEmpty()); //returns true if set has zero elements in it
USER_DEBUG [3]|DEBUG|{80, 85, 90, 95}
USER_DEBUG [4]|DEBUG|true
USER_DEBUG [9]|DEBUG|{EC301, EC302}
USER_DEBUG [11]|DEBUG|2
USER_DEBUG [12]|DEBUG|false

Please note if two set elements only differ by case are consider as distinct elements. This makes set case sensitive collection.

Please refer Set Class, for more information and list of supported methods.

Set<String> countries = new Set<String>();
countries.add('Finland');
countries.add('Switzerland');
countries.add('Norway');
countries.add('norway');
System.debug(countries);
USER_DEBUG [6]|DEBUG|{Finland, Norway, Switzerland, norway}

Maps

A map is a collection of key-value pair. In map keys must be unique so they are handled internally using set like mechanism to enforce uniqueness. Value corresponding to key can be duplicate hence managed using list mechanism. Key value pair in apex can be of any type – primitive types, collections, sObjects, user-defined types, and built-in apex types.

How to declare a Map ?

Map<String,String> idValue;
System.debug(idValue);

Map<String,String> countryVsCapitals = new Map<String,String>();
System.debug(countryVsCapitals);

Map<Integer,Decimal> rollNosVsMarks = new Map<Integer,Decimal>{
    158064 => 82.59,
    158065 => 79.25,
    158066 => 80.21
};
System.debug(rollNosVsMarks);
USER_DEBUG [2]|DEBUG|null
USER_DEBUG [5]|DEBUG|{}
USER_DEBUG [12]|DEBUG|{158064=82.59, 158065=79.25, 158066=80.21}

General Purpose Map Methods

Map<Id,Opportunity> oppRecs = new Map<Id,Opportunity>([SELECT Id, Name, StageName FROM Opportunity LIMIT 3]);
System.debug(oppRecs);

Map<String,String> countryVsCapitals = new Map<String,String>();
//put(key,value) associate specified key with specified value.
countryVsCapitals.put('Finland','Helsinki');
countryVsCapitals.put('Sweden','Stockholm');
countryVsCapitals.put('Austria','Vienna');
System.debug(countryVsCapitals);

//get(key) returns the value associated with specified key
System.debug(countryVsCapitals.get('Finland'));

//containsKey(key) returns true if specified key present in map
System.debug(countryVsCapitals.containsKey('Austria'));
System.debug(countryVsCapitals.containsKey('USA'));

System.debug(countryVsCapitals.isEmpty());//returns true if no key-value pair present in map
System.debug(countryVsCapitals.size()); //returns number of key-value pair present in map
System.debug(countryVsCapitals.keySet()); //returns set containing all keys from map
System.debug(countryVsCapitals.values()); //returns list containing all values from map
USER_DEBUG [2]|DEBUG|{0062w00000JzF1UAAV=Opportunity:{Id=0062w00000JzF1UAAV, Name=Edge Emergency Generator, StageName=Closed Won}, 0062w00000JzF1bAAF=Opportunity:{Id=0062w00000JzF1bAAF, Name=Edge Installation, StageName=Closed Won}, 0062w00000JzF1cAAF=Opportunity:{Id=0062w00000JzF1cAAF, Name=Edge SLA, StageName=Closed Won}}
USER_DEBUG [9]|DEBUG|{Austria=Vienna, Finland=Helsinki, Sweden=Stockholm}
USER_DEBUG [12]|DEBUG|Helsinki
USER_DEBUG [15]|DEBUG|true
USER_DEBUG [16]|DEBUG|false
USER_DEBUG [18]|DEBUG|false
USER_DEBUG [19]|DEBUG|3
USER_DEBUG [20]|DEBUG|{Austria, Finland, Sweden}
USER_DEBUG [21]|DEBUG|(Helsinki, Stockholm, Vienna)

A map key can hold null value and if key is not specified in map and used inside get(key) method it returns null value.

Map<String,String> countryVsCapitals = new Map<String,String>();
countryVsCapitals.put('Finland','Helsinki');
countryVsCapitals.put('Sweden','Stockholm');
countryVsCapitals.put('Austria','Vienna');
countryVsCapitals.put(null,'London');

System.debug(countryVsCapitals.get('Finland'));
System.debug(countryVsCapitals.get(null));
System.debug(countryVsCapitals.get('Iceland'));
USER_DEBUG [7]|DEBUG|Helsinki
USER_DEBUG [8]|DEBUG|London
USER_DEBUG [9]|DEBUG|null

Please refer Map Class, for more information and list of supported methods.

Best Practices of Collections

  1. Choose the right collection type.
    • Use maps for Data Aggregation and grouping, Serializing and deserializing, etc.
    • Use sets for query optimization by reducing number of duplicate items, etc.
    • Use lists where sequence and order matters.
  2. Avoid nested loops as they leads to performance issues. Consider using maps to avoid nested loops.
  3. Use collections for DML operations. This helps to reduce number of DML operations in transaction and improves performance.
  4. Handle null values as well as empty collection. Otherwise, it may cause, System.NullPointerException: Attempt to de-reference a null object or System.ListException: List index out of bounds. Use not equal null check, isEmpty(), or size() methods to ensure data is present in collections. For map use containsKey(key) to check if key is present or not.
  5. Use Collections while fetching records of sObjects. To avoid System.QueryException: List has more than 1 row for assignment to SObject and System.QueryException: List has no rows for assignment to SObject.

Collections are fundamental data structures in Apex. They provide developers with means to manage data effectively, optimize performance, Bulk data processing, optimizing resource utilization etc. Using collections essential for writing efficient, scalable, and maintainable code.

You may also like...

Leave a Reply

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