Bug in List.contains for Id data type?

Looks like this bug System.hashCode broken on Id properties of SObjects? remains unfixed.

Diagnosis is made more confusing because of this hashCode() is never called when adding to Maps and Sets where the debug level determines if hashCode is called or not.


Sounds like it may be an edge case; it returns true in my org:

09:28:48.2 (4756791)|SYSTEM_METHOD_ENTRY|[7]|System.debug(ANY)
09:28:48.2 (4767250)|USER_DEBUG|[7]|DEBUG|true
09:28:48.2 (4775541)|SYSTEM_METHOD_EXIT|[7]|System.debug(ANY)

Please consider submitting a bug if you have a valid reproduction that support can use. In the general case, you should be able to use contains as intended.


I can repo this on na37.

List<Id> myIdList = new List<Id>();
myIdList.add('0060E000008PdMk');

Id oppId ='0060E000008PdMk';   

System.assert(oppId == myIdList[0]); // true 
System.assert(myIdList.contains(oppId)); // false - assertion failed !! 

Changing the types of the List and the variable to String causes this code to run as expected.


It looks like the HashCodes under the surface don't match up. This example casts our ids to objects, and calls HashCode on them, then compares them. They fail, despite the values being the same.

You can cause the contains to find the value by changing the debug level of "Apex Code" to FINEST. This (According to @KeithC) causes the comparison to not use HashCode and use equals instead, and results in a true value from contains.

List<Id> myIdList = new List<Id>();
// Added extra characters to ensure it wasnt something with 15/18 char ids 
myIdList.add(((Id)'0060E000008PdMkOIP'));

Id oppId = '0060E000008PdMkOIP';  

Integer oppHash = ((Object)oppId).hashCode();
Integer listHash = ((Object)myIdList[0]).hashCode();

System.assertEquals(oppHash, listHash); // !! Fails!! - hash values differ  

System.assert(oppId.equals(myIdList[0])); // true

// !! Setting debug APEXCODE to FINEST results in true 
System.assert(myIdList.contains(oppId)); // false 

Tags:

Apex