Looking at legacy code. The developer is loading Account.ID and a Lookup field value. I would think the best map would be Map<Id,Id> but this was coded as Map<string,string>. The value can be NULL.

Any reason/benefit to declaring it with strings versus IDs?


Using Map<Id, Id> over Map<String, String> has at least two benefits I can think of.


The more restricted type identifies that this isn't just a map of string-string key-value pairs, it is specifically a map of id-id key-value pairs. An experienced programmer, in particular, will immediately understand that we're making a link between records via their ID values. The string-string version leaves ambiguity if used improperly, so one should prefer the id-id version when practical (and, alternatively, Map<Id, String> and Map<String, Id>, if that's the intended use case).

Runtime Conversion

Sometimes we have to deal with 15-character and 18-character Id values. Mix them up in a map with a string key and you'll introduce logic bugs, since 001000000012345 is not the same as 001000000012345AAA. Using the correct key removes the possibility of a false negative when checking if a key is present or getting the associated value.

In summary, using the correct data type helps make the code self-documenting and introduces clarity in to the code, especially for the next person who's unfamiliar with the code (possibly including you a year from now). In some edge cases, it can also prevent false negatives by coercing the data into the correct format, either by the compiler or at runtime, and logic bugs can be easily identified when the correct type is used (e.g. if you try to put a non-ID into an Id key, you'll get an exception).

In any case, there is no benefit for using Map<String, String> over Map<Id, Id> when the situation calls for using Id values. Instead, it only risks the possibility of logic bugs and confusion.


I'd say there is no benefit, and that it is worse to store an Id in a String1.

Using an Id gives you a compile-time check that you are, in fact, using something that could possibly be an Id

  • "0010000000ATest" can currently be, and is likely, the Id for someone's account
  • "0010RandomATest" looks like an Id at first glance, but cannot be an Id at time of writing due to this answer on the Salesforce Id format (thanks sfdcfox for pointing me to that link)

An Id also gives you access to the getSObjetType() method, which can come in handy if/when you start abstracting logic to a point where you're dealing with collections of SObjects (as opposed to a List<Account> or a Map<Id, Case>).

Map<Id, Id> is the right choice here, though a Map<String, String> isn't the end of the world.

1: Such situations should be rare. I have run into a situation where I couldn't avoid storing an Id as a String. This was when I needed to "relate" an SObject to OpportunityLineItem, which we cannot have lookup or master-detail relationships to.

  • 1
    Actually, the sixth position is currently "reserved" and must always be 0. It's a simple check, but can definitely help identify if you're trying to abuse an arbitrary string as an Id. There's another answer here that goes in to more details. TMYK.
    – sfdcfox
    Oct 4 '18 at 15:01
  • @sfdcfox Today I learned.
    – Derek F
    Oct 4 '18 at 15:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.