Take the 2-minute tour ×
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.

Do Apex collection classes implement Iterable interface? I want to write a generic function that can take any of the collection classes that support foreach. Is this possible?

share|improve this question

3 Answers 3

up vote 5 down vote accepted

The List<ANY> class implements Iterable<ANY>, but neither Map<ANY, ANY> nor Set<ANY> does.

Try the following code in v30:

System.debug((new set<id>()) instanceOf Iterable<Object>);
System.debug((new list<id>()) instanceOf Iterable<Object>);
System.debug((new map<id, object>()) instanceOf Iterable<Object>);
System.debug((new set<id>()) instanceOf Iterator<Object>);
System.debug((new list<id>()) instanceOf Iterator<Object>);
System.debug((new map<id, object>()) instanceOf Iterator<Object>);

Output:

12:30:33.073 (73681264)|USER_DEBUG|[1]|DEBUG|false
12:30:33.073 (73971363)|USER_DEBUG|[2]|DEBUG|true
12:30:33.074 (74136981)|USER_DEBUG|[3]|DEBUG|false
12:30:33.074 (74346453)|USER_DEBUG|[4]|DEBUG|false
12:30:33.074 (74526971)|USER_DEBUG|[5]|DEBUG|false
12:30:33.074 (74793803)|USER_DEBUG|[6]|DEBUG|false

So, in short, you need to handle each individually.

share|improve this answer

No, to my knowledge there is no way to use same code to iterate over Lists, Sets and Maps. You would have to provide 3 different entry points for your logic (override methods with different parameters perhaps) and wrap the rest in a function.

Additionally, you won't be able to reuse your code for anything other than sObjects or your custom object hierarchy since Salesforce doesn't support parametrised interfaces after api v26.0 (see comments to the answer of this question)

share|improve this answer
1  
Lists do indeed implement Iterable<ANY> (see my answer), but Sets and Maps do not. I posted an idea on the IdeaExchange about this, since it directly affects the ability to use things like String.join(Iterable<ANY>, String). –  sfdcfox Apr 30 at 18:34

List and Set not both being directly iterable via something like a common Collection interface is frustrating.

Not sure when it was introduced and it is not documented but Set does have an iterator method so you could write methods that take an Iterator but that is fairly ugly:

@isTest
private class A {
    @isTest
    static void iterateList() {
        System.assertEquals(1 + 2 + 3, sum(new List<Integer>{1, 2, 3}.iterator()));
    }
    @isTest
    static void iterateSet() {
        System.assertEquals(4 + 5, sum(new Set<Integer>{4, 5, 5}.iterator()));
    }
    private static Integer sum(Iterator<Integer> iter) {
        Integer sum = 0;
        while (iter.hasNext()) {
            sum += iter.next();
        }
        return sum;
    }
}

Writing methods that accept a List and wrapping sets in lists is what I have been doing:

@isTest
private class B {
    @isTest
    static void iterateList() {
        System.assertEquals(1 + 2 + 3, sum(new List<Integer>{1, 2, 3}));
    }
    @isTest
    static void iterateSet() {
        System.assertEquals(4 + 5, sum(new List<Integer>(new Set<Integer>{4, 5, 5})));
    }
    private static Integer sum(List<Integer> l) {
        Integer sum = 0;
        for (Integer i : l) {
            sum += i;
        }
        return sum;
    }
}

(Don't think Map really belongs directly in this discussion.)

share|improve this answer

Your Answer

 
discard

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.