2

I am tring to add list of string to set of Id . i am trying to avoid one more for loop to again loop and convert using Id.valueOf(). Help me to achieve it.

Map<String,Set<String>> delegationDataMap // Value retrieved from some other function call 
Set<Id> permSetIds = new Set<Id>();
for (List<String> permSetSubSet : delegationDataMap.values()){
    permSetIds.add((Set<Id>)permSetSubSet);// Struggling here
}

Thank you all .I found answer from this article

for(Set<String> permSetSubSet : delegationDataMap.values()){            
    permSetIds.addAll(new Set<Id>((List<Id>)new List<String>(permSetSubSet)));
}

Now what is the most efficient way of this conversion. will JSON step ahead of this ?

4 Answers 4

3

JSON is a CPU hog; you may as well loop over your Set and cast each element individually at that point. You should not use JSON for converting a list to a set or vice versa. As an aside, you're also abusing a compiler bug by casting a List<String> to a List<Id>. You should be prepared for runtime exceptions if you do this. Realistically, you should fix the delegationDataMap to be Map<String, Set<Id>> if it really is meant to be a set of Id values.

0
2

You could use related good solution answered by Peter Knolle.

Here is an example based on your code:

Map<String, Set<String>> mapOfSet = new Map<String, Set<String>>{
    'a' => new Set<String> {'Id 1', ..},
    'b' => new Set<String> {'Id2', ..}
};
Set<Id> setOfId = new Set<Id>();
for(Set<String> s: mapOfSet.values()) {
    setOfId.addAll((Set<Id>) JSON.deserialize(JSON.serialize(s), Set<Id>.class));
}

System.debug('==' + setOfId);
1

You can use JSON class for this:

Map<String,Set<String>> delegationDataMap // Value retrieved from some other function call 
Set<Id> permSetIds = new Set<Id>();
for (List<String> permSetSubSet : delegationDataMap.values()){
    permSetIds.addAll((Set<Id>)JSON.deserialize(JSON.serialize(permSetSubSet), Set<Id>.class));
}
0

As much as I love clever solutions, I think in this case you will get the best readability and maintainability by just doing a normal loop (plus it gives you better error handling):

Map<String,Set<String>> delegationDataMap;
Set<Id> permSetIds = new Set<Id>();
for (List<String> permSetSubSet : delegationDataMap.values())
{
    for(String element : permSetSubSet)
    {
        if (element instanceof ID)
        {
            permSetIds.add(element);
        }
        else
        {
            System.debug('Attempted to add invalid ID: ' + element);
        }
    }
}
5
  • This is never going to add the element in permSetIds since it is of type String. It always will go to exception.
    – SfdcBat
    Jun 8, 2017 at 20:13
  • 1
    @SfdcBat ID and String values are implicitly convertible, so no exception is thrown if the string is a valid ID. In fact, it is possibly noteworthy that this will only check that the string is in a valid ID format, it does not check that the ID actually exists in the system. Jun 8, 2017 at 20:43
  • Thank you for the clarification. I used an invalid id format with random string as '23384737' to test it. Now it seems like it checks whether the string has 15 char or 18 char , if not it throws an exception
    – SfdcBat
    Jun 8, 2017 at 20:51
  • @SfdcBat Yeah, it doesn't even check for invalid base-62 characters. They probably figured invalid IDs would be caught upon any database transaction anyway. Jun 8, 2017 at 21:11
  • @IllusiveBrian the first five characters and the last three (in 18-character Id values) do have some validation. It's therefore possible to run into exceptions on seemingly valid Id values. The 4th through 15th character positions are not validated until you hit the database.
    – sfdcfox
    Jun 12, 2017 at 12:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .