Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a bit of code where I've written a SOQL query that returns a list of SObject records, however I need a Set<Id> structure to pass to another method that I don't have control of (and thus can't change the method signature of).

How can I turn my returned List<SObject> into a Set<Id>? Is the best option just a for loop?

share|improve this question
don't go with the for loop, use a map constr... oh, nevermind :P – bigassforce Feb 26 '13 at 1:24
up vote 86 down vote accepted

This trick only works on the Id field, but you can use the Map constructor that accepts an SObject list to do this without consuming a script statement for each element in the List.

For example:

List<SObject> results = Database.query(someSOQL);
Set<Id> resultIds = (new Map<Id,SObject>(results)).keySet();

What this second line does is create a new Map<Id,SObject> from the results list using a special constructor, and then take the map's set of keys via the keySet() method. Then the map falls out of scope and it's heap space is released, leaving you with a very governor-efficient set.

share|improve this answer
greased lightning! – bigassforce Feb 26 '13 at 1:23
One thing to watch out for if you need to modify the set... You'll get a System.FinalException: Collection is read-only error if you try to add to the resultIds. To get around that you need to create a new set, e.g., Set<Id> resultIds = new Set<Id> (new Map<Id,SObject>(results).keySet()); – Peter Knolle Feb 26 '13 at 1:27
or clone the Set Set<Id> resultIds = (new Map<Id,SObject>(results)).keySet().clone(); – Daniel Blackhall Feb 26 '13 at 1:37
Worth noting is that if all that you are doing is using the Set<Id> in a bind expression then you can don't need to create the Set and can actually just use the List<sObject>. For example: List<Opportunity> opps = [Select Id,Name From Opportunity Where AccountId = :[Select Id, Name From Account Limit 100]]; works. – Peter Knolle Feb 26 '13 at 16:05
Any workaround for a field different from the Id one? – jonathanwiesel Jul 17 '14 at 21:46

If you are not using Dynamic SOQL, you can skinny this down to a one-liner like this...

Set<Id> ids = (new Map<Id, Lead>([SELECT Id FROM Lead])).keySet();

This is how you would do it with Dynamic SOQL but you must cast...

Set<Id> ids = (new Map<Id, Lead>((List<Lead>)Database.query(query))).keySet();

This unresolved bug is why you must cast the returned List<SObject>

share|improve this answer
Seriously, that issue is still unresolved? I miss Rich Unger so much... – ca_peterson Feb 26 '13 at 16:02

There is an issue with the accepted methodology that can come up if you are not sure each element is in the list only once. It won't matter if you are sure the input is a SOQL result, but if you are writing a utility where you need to get the desired Set<Id> without knowing the source of the List<SObject>, it may be necessary to adopt a different approach.

The bug can be demonstrated fairly simply, though I don't have a less contrived use case handy.

Lead record = [SELECT Id FROM Lead LIMIT 1];
List<Lead> recordsWithDuplicate = new List<Lead> { record, record };
Set<Id> recordIds = new Map<Id, Lead>(recordsWithDuplicate);

The above snippet results in:

System.ListException: Row with duplicate Id at index: 1

To avoid that, you can use putAll, though it may actually be slower than just using a for loop.

Map<Id, Lead> recordsMap = new Map<Id, Lead>();
Set<Id> recordIds = recordsMap.keySet();

One more note, I take issue with the contention that the results of Database.query must be cast to get the Set<Id>. The following compiles and executes without issue:

public static Set<Id> getRecordIds(SObjectType token)
    return new Map<Id, SObject>(Database.query('SELECT Id FROM ' + token)).keySet();
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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