Hot answers tagged

27

(tl;dr at bottom) Filter Speed If you can use Map.keySet(), you'll get a Set back in about 1/10th of the time versus a loop over those same records and adding all the values. Of course, the Map<Id, SObject>(List<SObject>) constructor only works on Id, not on related ID values, which means you'd have to fall back to a loop. However, in cases ...


15

One reason may be that Set<SObject> is a risky mechanism to use: equality is based on all the fields (so is expensive) and if fields are changed logic can easily break. Same problem using SObject as a Map key. So not a pattern to be encouraged. But perhaps just because also supporting Set<SObject> adds a bunch of extra methods that need ...


14

Update: I missed what is probably the single most important part of the question in answering this - the "In SOQL" part. Perhaps consider this answer in terms of the other processing you are going to do with the collection before or after you pass it off to a SOQL query. Summary: Use a List when: Ordering is important You want to access elements by index ...


14

No. Any field variation will cause the records to hash differently, even if they have the same Id. This is why Map<Id, SObject> is preferable. Id commonId = '001000000000000AAA'; Account a = new Account(Id=commonId, Name='A'); Account b = new Account(Id=commonId, Name='B'); Set<Account> records = new Set<Account> { a, b }; system....


12

From the Trigger Context Variables documentation: Trigger.new: this sObject list is only available in insert and update triggers Trigger.newMap: this map is only available in before update, after insert, and after update triggers In a "before insert" trigger, the sObjects don't yet have ID values so a Trigger.newMap keyed by the sObject ID can't be made ...


11

I wasn't satisfied with the accepted answer, specifically relating to the VisualForce aspect of it, so I performed some additional testing on this critical fix with regard to VF. What I learned is that when a VF iterator (apex:pageBlockTable, apex:repeat, etc.) is used against a Map, one of its undescribed actions is to sort the keys. This completely ...


11

It took 2 months, but this is the "final" answer we got from Support on this topic. Note that the investigation by Tier 3 resulted in this Known Issue being filed which was ultimately the cause for our documented behavior (i.e. by setting a log filter override on a class with a hashCode()/equals() implementation, it effectively disabled hashCode() from being ...


11

Approach This should be my final update. I reran my tests, setting all Debug Levels to NONE except Apex, which I set to ERROR. The findings are more or less unchanged: casting beats all other approaches. I added more data, however, to demonstrate the level of difference more rigorously. I used the following strategy to profile the above in Execute ...


9

Note that you are calculating the Set Complement. The set methods are 16x-25x faster. I ran 20 trials each with the following configurations, all with Set<Integer> of 1000 elements to generate the data below. TL;DR When there is 100% overlap, the Set methods are about 26 times faster. When there is 0% overlap, the difference is a factor of about 16. ...


8

The Set collection type does not allow you to implicitly cast, unlike with List. You can, however, overload the signature to work around the issue. You have to do some tricky maneuvering to genericize the collection, but it can be done. public class Demo { public Boolean doStuff(Set<Object> values) { return values.isEmpty(); } ...


8

I think that the problem is in javascript when you are declaring mySet. Try this: var mySet = new Set(component.get("v.mySet")); Edit: the best solution is var changes = cmp.get("v.changes") || new Set();


8

One explanation may be that the underlying Java HashMap code behaves that way; this HashMap source code includes this code: 884 public Set<K> More ...keySet() { 885 Set<K> ks = keySet; 886 return (ks != null ? ks : (keySet = new KeySet())); 887 } 888 889 private final class KeySet extends AbstractSet<K> { 890 ...


7

It appears to be a problem with the Apex compiler. It isn't rejecting the Set as an invalid parameter to the Map constructor (as per Lance's answer). Note that you can't explicitly cast between Set, List and Map or perform an instanceOf check between them. Doing so gives a compiler error like: Incompatible types since an instance of SET is never an ...


7

You have to loop through and use addAll. There is no shortcut. Set<String> allValues = new Set<String>(); for (Set<String> subset : st.values()) { allValues.addAll(subset); }


7

Equality and the hash code value are based on all the properties of the SObject which makes sense. But when an object is placed in a hashMap, the hash code is used to determine which "bucket" the object reference is placed in at add time. So if you then change any property of the object after that, it is highly likely that the object reference will be lost ...


6

My suggestion: just turn it on and test it on a sandbox or developer org. Should become pretty clear. Update: reading MarkPonds comment on behavior in VF, I would recommend to stick with the current pattern sfdcfox describes using sorted lists from keysets as iterators. The weird and incomplete documentation might be a hint that this isn't shipped as a big ...


6

When you perform a comparison between a String and an Id (e.g. ==, !=, or <>), then the other argument is "promoted" to an Id value. All Id values must be 15 or 18 characters long, and must contain only A-Z, a-z, and 0-9, so '' is not a valid Id. Proof: String a = ''; Id b; System.assert(a != b); Edit: Also, there's a more efficient way you could ...


6

You need to first combine all the Set<Id> into one Set<Id> in Apex code: Set<Id> allCaseIds = new Set<Id>(); for (Set<Id> ids : caseIdsByFlag.values()) { allCaseIds.addAll(ids); } ... WHERE CaseId IN :allCaseIds ...


6

emailMatchingContacts.values() will return List of the values of Map from key-value pairs. That will be List<Set<Id>> This will be resolved by either 1 of them: emailMatchingContacts should be of type Map<String,Id> OR . you should do matchingContactIds.addAll(emailMatchingContacts.get(key)) emailMatchingContacts.get(key) will return ...


5

I think perhaps the best way is to search if the opp.OwnerId is in a Map<User> that you can create from the result of your query. Map<Id,User> userMap = new Map<Id,User>([SELECT Id FROM User WHERE UserRole.Name like '%AE%' OR UserRole.Name like '%CM%']); Now you can iterate the opportunities and use containsKey() on the map to see if the ...


5

You could also use the .putAll() method to convert a list of sObjects to a map with the record Id as the key. Account a = [SELECT Id, Name FROM Account LIMIT 1]; List<Account> lsAccounts = new List<Account>{a,a}; Map<Id, Account> accounts = new Map<Id, Account>(); accounts.putAll(lsAccounts); System.debug('Map:' + accounts); The ...


5

This line: String s = tcId.pse__Project__r.pse__Region__r.ffpsai__OwnerCompany__r.Id(); Is no valid syntax as a field is not a method. Methods use the () notation. To get the ID of the OwnerCompany (Lookup field as you suggested) all you need is: String s = tcId.pse__Project__r.pse__Region__r.ffpsai__OwnerCompany__c;


5

Please apply system.debug('###########'+UID); before below line and check UID Is as a blank , I think UID is returning blank value in your case. Set<Id> UID = new Set <Id> (); UID.add(DM); UID.add(RM); system.debug('###########'+UID); UserTemp=[select Name , Id , Email from User where Id in : UID];


5

Apex collections are always passed by reference meaning that it is just a pointer to the original collection. If you want to create a new instance of a collection that can be independently modified you will want to use the clone() method on the collection. More information is available at https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/...


5

This interesting Apex oddity came up when I was debugging a problem around hash code collisions. Just by adding a System.debug statement that drops the contents of the Set it becomes possible to find the record in the Set again. Account a1 = new Account(name='a'); Account a2 = new Account(name='b'); Set<Account> accountSet = new Set<Account>{a1,...


5

It's kind of awkward, but I've always just used a third set: Set<String> firstSet = new Set<String>(), secondSet = new Set<String>(), thirdSet = new Set<String>(); // populate first and second set // then... thirdSet.addAll(firstSet); thirdSet.retainAll(secondSet); // And yet later... // There was at least one overlapping value ...


5

There is a standard Set method, called retainAll. That method remove all elements in original set, except from set in parameter (save in current set intersection of the two sets) and returns true if original set has been changed during operation. For example: Set<Integer> s1 = new Set<Integer>{1,2,3}; Set<Integer> s2 = new Set<Integer&...


5

It's not a read-only map, per se (the error is shared with other truly read-only collections, like Trigger.new). It allows you to remove values, which also removes them from the map. You can use the removeAll, retainAll, remove, and clear methods to remove some or all of the mapped value pairs. I actually wish they allowed add and addAll methods, because it ...


5

For any User defined type, you need to implement the equals and hashCode methods. Refer to the below excerpt from the documentation. Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objects’ fields....


5

What you have observed is expected behavior: null is a valid collection element, and containing it makes the collection non-empty.


Only top voted, non community-wiki answers of a minimum length are eligible