As a Salesforce developer, I find I frequently need to extract Sets from List<SObject>, so I'm looking to create a generalized way of creating Sets.

The problem is, Salesforce thinks Set<Object> is never an instance of Set<Id>, Set<String>, etc.

I've created this helper class:

    private class SetExtractor {
        SObjectField extractedField;
        XAP_PRED_SObjectPredicateIntf predicate;

        SetExtractor(SObjectField extractedField, XAP_PRED_SObjectPredicateIntf predicate) {
            this.extractedField = extractedField;
            this.predicate = predicate;

        SetExtractor(SObjectField extractedField) {
            this(extractedField, new XAP_PRED_SObjectFieldHasNonBlankValue(extractedField) 

        public Set<Object> extractFrom(List<SObject> sObjectList) {
            Set<Object> resultSet = new Set<Object>();
            for (SObject sObj : sObjectList) {
                if (this.predicate.isTrueFor(sObj)) {
            return resultSet;

This is the Predicate interface:

public interface XAP_PRED_SObjectPredicateIntf {
    Boolean isTrueFor(SObject sObj);

I can solve the problem of converting from Set<Object> to Set<Id> using serialize/deserialize, for example:

public virtual Set<Id> extractNonNullIdsFrom(List<SObject> sObjectList, SObjectField idField) {
    Set<Object> objectSet = new SetExtractor(idField)
    return (Set<Id>) JSON.deserialize(JSON.serialize(objectSet), Set<Id>.class);

But it is my understanding that serialize/deserialize are expensive operations.

Alternatively, instead of initially extracting a Set, I could extract a List, i.e.:

public virtual Set<Id> extractNonNullIdsFrom(List<SObject> sObjectList, SObjectField idField) {
    List<Object> objectList = new ListForSetExtractor(idField)
    return new Set<Id>((List<Id>)objectList);
  • I'm wondering if there is a downside to this later approach?
  • Would the size of either the source sObjectList or the result objectList matter?
  • If so, what might be a good way to determine the tipping point?

Why not just use Map Constructor? and then use the keySet to get Set?

Set<Id> resultIds = (new Map<Id,SObject>(sObjectList)).keySet();
  • Good question... Let me share more code to make it more clear what I am doing. :-) – Brian Kessler May 1 '19 at 15:17
  • I've added some code. By the way, you'll notice that here I'm not just getting the keySet, but possibly any Ids contained in the SObject. Or, more abstractly, I could get any set of values which meets the predicate criteria. – Brian Kessler May 1 '19 at 15:24

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.