{"id":180,"date":"2014-12-29T01:35:26","date_gmt":"2014-12-28T20:35:26","guid":{"rendered":"http:\/\/learnsf.wordpress.com\/?p=180"},"modified":"2014-12-29T01:35:26","modified_gmt":"2014-12-28T20:35:26","slug":"trick-how-to-obtain-a-map-indexed-by-any-field-not-just-id-faster-and-without-loops","status":"publish","type":"post","link":"https:\/\/blog.felineflock.com\/index.php\/2014\/12\/29\/trick-how-to-obtain-a-map-indexed-by-any-field-not-just-id-faster-and-without-loops\/","title":{"rendered":"Trick:  How to obtain a map indexed by any field (not just ID) faster and without loops!"},"content":{"rendered":"<p>Often we query an object and need to create a map out of the list of records retrieved. The most straightforward way is to declare a Map&lt;ID, sObject&gt; and initialize it with a\u00a0list resulting from a\u00a0SOQL query.<\/p>\n<blockquote style=\"width:90%;font-family:Monospace;\"><p>List&lt;Account&gt; acctList = [ SELECT ID, Name, AccountNumber<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM Account ];<\/p>\n<p>Map&lt;ID, Account&gt; acctMapByID = new\u00a0Map&lt;ID, Account&gt;( acctList );<\/p><\/blockquote>\n<p>The code shown above will populate the acctMapByID with accounts using their <strong>IDs<\/strong> as the key.<\/p>\n<p>However, what if we wanted to create a map <strong>indexed by AccountNumber instead<\/strong>? We would have to loop through the list and add the records to the map one by one specifying theAccountNumber as the key.<\/p>\n<blockquote style=\"width:90%;font-family:Monospace;\"><p>List&lt;Account&gt; acctList = [ SELECT ID, Name, AccountNumber<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM Account ];<\/p>\n<p>Map&lt;String, Account&gt; acctMapByNumber =<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new\u00a0Map&lt;String, Account&gt;();<\/p>\n<p>for( Account anAccount : acctList ) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;acctMapByNumber.put( anAccount.AccountNumber, anAccount );<br \/>\n}<\/p><\/blockquote>\n<p>Now what if there was\u00a0a way to do that without any loops and in a single line of code?<\/p>\n<blockquote style=\"width:90%;font-family:Monospace;\"><p><code>Map&lt;String, SObject&gt; acctMapByNumber\u00a0=<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MapCreator.createMapByIndex( acctList, 'AccountNumber' );<\/code><\/p><\/blockquote>\n<p>Below is the definition of the <strong>MapCreator class<\/strong> that allows that.<\/p>\n<blockquote style=\"width:90%;font-family:Monospace;\"><p><code>public class MapCreator {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;public static Map&lt;String, SObject&gt; createMapByIndex(<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;SObject&gt; aList, String indexField ) {<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ get the list in JSON format<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;String jsonList = JSON.serialize( aList );<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ remove enclosing []<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;jsonList = jsonList.substring( 1, jsonList.length() - 1 );<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ copy the indexField value in front of each<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/ {} group using RegEx substitution<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/ example result: value:{...\"indexField\":\"value\"...}<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;jsonList = '{' + jsonList.replaceAll(<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'(\\\\{.*?\"' + indexField + '\":\"(.*?)\"(,\".*?\")*\\\\},?)'<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;, '\"$2\":$1' ) + '}';<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;\/\/ create map from the modified JSON<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String, SObject&gt; changedMap =<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Map&lt;String, SObject&gt;) JSON.deserialize(<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jsonList, Map&lt;String, SObject&gt;.class );<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;return changedMap;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n<p>}<\/code><\/p><\/blockquote>\n<p>It first converts the list to a JSON string, then modifies the string to look as if it was a serialized Map. It does that by using RegEx to insert the index in front of each record in the string. It then deserializes the modified JSON string into a map.<br \/>\nIt doesn&#8217;t use any loops explicitly although there must be loops hidden in the RegEx and JSON method internal implementations, which are much faster. <\/p>\n<p>What would be the advantages of using this class instead of coding the loop?<\/p>\n<p>The\u00a0<strong>MapCreator class<\/strong> uses string replacement\/RegEx, which is faster than looping and creating map elements one by one.<\/p>\n<p>According to my tests, it runs faster than looping for lists of roughly 8 records or more. For 63 records, it should be 5 to 6 times faster depending on the size of the records.<\/p>\n<p>It might not be relevant for most of the situations but if you have a long running code that needs to be optimized, it might be worth a try.<\/p>\n<p><strong>PS.:<\/strong>  I fixed a problem with the way WordPress displays code that made it convert quotes and double-quotes to special characters. Now the code can be copied and pasted onto Salesforce.<br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Often we query an object and need to create a map out of the list of records retrieved. The most straightforward way is to declare a Map&lt;ID, sObject&gt; and initialize it with a\u00a0list resulting from a\u00a0SOQL query. List&lt;Account&gt; acctList = [ SELECT ID, Name, AccountNumber &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM Account ]; Map&lt;ID, Account&gt; acctMapByID = new\u00a0Map&lt;ID, Account&gt;( acctList [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[13],"tags":[],"class_list":["post-180","post","type-post","status-publish","format-standard","hentry","category-no-category"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts\/180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/comments?post=180"}],"version-history":[{"count":0,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/posts\/180\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/media?parent=180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/categories?post=180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.felineflock.com\/index.php\/wp-json\/wp\/v2\/tags?post=180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}