5

Consider this minimal example:

class Test {
    private String val;
    public Test(String str) {
        this.val = str.toLowerCase();
    }
    public Boolean equals(Object obj) {
        if (obj instanceOf Test) {
            return val == ((Test) obj).val;
        }
        return false;
    }
    public Integer hashCode() {
        return val.hashCode();
    }
}

Set<Test> a = new Set<Test>();
a.add(new Test('abc'));

Set<Test> b = new Set<Test>();
b.add(new Test('abc'));

b.retainAll(a);
System.debug(b);

Set b is emptied. This is similar to existing question, Apex Set retainAll() with custom class.

It appears like the retainsAll ignores equals and hashCode and instead works with references, because the snippet below will work as expected:

Test abc = new Test('abc');
Set<Test> a = new Set<Test>();
Set<Test> b = new Set<Test>();
a.add(abc);
b.add(abc);
b.retainAll(a);
System.debug(b);

If we create separate references, like Test bar = new Test('abc') and Test foo = new Test('abc'), bar.equals(foo), foo.equals(bar) and bar.hashCode() == foo.hashCode(), but the set b is cleared.

  • Sometimes, the set is emptied if it is debugged before calling retainAll, but not emptied if it is debugged after calling retainAll. – ipavlic Aug 9 '18 at 0:28
  • This definitely looks like a bug in the core implementation. And the reason I say is because I wrote this piece of code (all versions in your post) in Java with a HashSet (and that the Apex API are based on Java interface) and could see the expected behavior. The original set did not change, i.e., it retained the value as expected. – Jayant Das Aug 9 '18 at 1:18
0

After much time wasting, Salesforce has decided to agree that this is a bug: https://success.salesforce.com/issues_view?title=the-result-of-set-sobject-retainall-set-sobject-are-inconsistent-between-apexcode-log-level-is-finest-and-it-is-finer-or-lower&Id=a1p3A000001HlAf

|improve this answer|||||

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.