Remove from map doesn’t work

I’m obviously missing something here.
I’m trying to remove a key-value from a map using the “remove” function but the remove function returns null, as if the key doesn’t exist in the map.
As you can see from the debug log, the map contains the key and the “get” function works for this key on this map.
The list is a list of the type of the value in the map (Tier__c). I tried creating a local Tier__c variable that will get the result of the remove but the remove function still return null.
Please see the code and the debug log below.

Code:

//Go through active tiers.
for(integer i = 0; i < map_plIdToTiers.get(priceListId).size(); i++)
{
    system.debug('Gad --> map_plIdToFTiers.get(priceListId).containsKey(i+1): ' + map_plIdToFTiers.get(priceListId).containsKey(i+1));
    //Check if we don't have future tier for this tier sequence.
    if(!map_plIdToFTiers.get(priceListId).containsKey(i+1))
    {
        system.debug('Gad --> i+1: ' + (i+1));
        system.debug('Gad --> map_plIdToTiers.get(priceListId): ' + map_plIdToTiers.get(priceListId));
        system.debug('Gad --> map_plIdToTiers.get(priceListId).get(i+1): ' + map_plIdToTiers.get(priceListId).get(i+1));
        system.debug('Gad --> map_plIdToTiers.get(priceListId).containsKey(i+1): ' + map_plIdToTiers.get(priceListId).containsKey(i+1));
        system.debug('Gad --> lst_tiersToDelete before: ' + lst_tiersToDelete);
        //Remove the active tier and rate for this tier sequence.
        lst_tiersToDelete.add(map_plIdToTiers.get(priceListId).remove(i+1));
        lst_ratesToDelete.add(map_plIdToRates.get(priceListId).remove(i+1));
        system.debug('Gad --> map_plIdToTiers.get(priceListId).get(i+1): ' + map_plIdToTiers.get(priceListId).get(i+1));
        system.debug('Gad --> lst_tiersToDelete after: ' + lst_tiersToDelete);
    }
}

Debug log:

21:57:11.028 (6028457431)|USER_DEBUG|[344]|DEBUG|Gad --> map_plIdToFTiers.get(priceListId).containsKey(i+1): false
21:57:11.028 (6028461927)|SYSTEM_METHOD_EXIT|[344]|System.debug(ANY)
21:57:11.028 (6028473555)|SYSTEM_METHOD_ENTRY|[346]|Map<Id,Map<Decimal,Future_Tier__c>>.get(Object)
21:57:11.028 (6028489242)|SYSTEM_METHOD_EXIT|[346]|Map<Id,Map<Decimal,Future_Tier__c>>.get(Object)
21:57:11.028 (6028500906)|SYSTEM_METHOD_ENTRY|[346]|Map<Decimal,Future_Tier__c>.containsKey(Object)
21:57:11.028 (6028519955)|SYSTEM_METHOD_EXIT|[346]|Map<Decimal,Future_Tier__c>.containsKey(Object)
21:57:11.028 (6028549042)|SYSTEM_METHOD_ENTRY|[348]|String.valueOf(Object)
21:57:11.028 (6028577758)|SYSTEM_METHOD_EXIT|[348]|String.valueOf(Object)
21:57:11.028 (6028597392)|SYSTEM_METHOD_ENTRY|[348]|System.debug(ANY)
21:57:11.028 (6028602961)|USER_DEBUG|[348]|DEBUG|Gad --> i+1: 3
21:57:11.028 (6028607397)|SYSTEM_METHOD_EXIT|[348]|System.debug(ANY)
21:57:11.028 (6028631145)|SYSTEM_METHOD_ENTRY|[349]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.028 (6028659330)|SYSTEM_METHOD_EXIT|[349]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.028 (6028678060)|SYSTEM_METHOD_ENTRY|[349]|String.valueOf(Object)
21:57:11.028 (6028791518)|SYSTEM_METHOD_EXIT|[349]|String.valueOf(Object)
21:57:11.028 (6028808625)|SYSTEM_METHOD_ENTRY|[349]|System.debug(ANY)
21:57:11.028 (6028814224)|USER_DEBUG|[349]|DEBUG|Gad --> map_plIdToTiers.get(priceListId): {1=Tier__c:{Id=a1Hm0000000HYvAEAW, RecordTypeId=012m00000000QuiAAE, Price_List__c=a0mm0000006xFhrAAE, Tier_Seq__c=1}, 2=Tier__c:{Id=a1Hm0000000HYvBEAW, RecordTypeId=012m00000000QuiAAE, Price_List__c=a0mm0000006xFhrAAE, Tier_Seq__c=2}, 3=Tier__c:{Id=a1Hm0000000HYvCEAW, RecordTypeId=012m00000000QuiAAE, Price_List__c=a0mm0000006xFhrAAE, Tier_Seq__c=3}}
21:57:11.028 (6028821485)|SYSTEM_METHOD_EXIT|[349]|System.debug(ANY)
21:57:11.028 (6028845036)|SYSTEM_METHOD_ENTRY|[350]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.028 (6028874361)|SYSTEM_METHOD_EXIT|[350]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.028 (6028889328)|SYSTEM_METHOD_ENTRY|[350]|Map<Decimal,Tier__c>.get(Object)
21:57:11.028 (6028913686)|SYSTEM_METHOD_EXIT|[350]|Map<Decimal,Tier__c>.get(Object)
21:57:11.028 (6028931030)|SYSTEM_METHOD_ENTRY|[350]|String.valueOf(Object)
21:57:11.028 (6028987899)|SYSTEM_METHOD_EXIT|[350]|String.valueOf(Object)
21:57:11.029 (6029004379)|SYSTEM_METHOD_ENTRY|[350]|System.debug(ANY)
21:57:11.029 (6029010773)|USER_DEBUG|[350]|DEBUG|Gad --> map_plIdToTiers.get(priceListId).get(i+1): Tier__c:{Id=a1Hm0000000HYvCEAW, RecordTypeId=012m00000000QuiAAE, Price_List__c=a0mm0000006xFhrAAE, Tier_Seq__c=3}
21:57:11.029 (6029016523)|SYSTEM_METHOD_EXIT|[350]|System.debug(ANY)
21:57:11.029 (6029039967)|SYSTEM_METHOD_ENTRY|[351]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029068771)|SYSTEM_METHOD_EXIT|[351]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029083751)|SYSTEM_METHOD_ENTRY|[351]|Map<Decimal,Tier__c>.containsKey(Object)
21:57:11.029 (6029104409)|SYSTEM_METHOD_EXIT|[351]|Map<Decimal,Tier__c>.containsKey(Object)
21:57:11.029 (6029121190)|SYSTEM_METHOD_ENTRY|[351]|String.valueOf(Object)
21:57:11.029 (6029135991)|SYSTEM_METHOD_EXIT|[351]|String.valueOf(Object)
21:57:11.029 (6029149087)|SYSTEM_METHOD_ENTRY|[351]|System.debug(ANY)
21:57:11.029 (6029154444)|USER_DEBUG|[351]|DEBUG|Gad --> map_plIdToTiers.get(priceListId).containsKey(i+1): true
21:57:11.029 (6029158941)|SYSTEM_METHOD_EXIT|[351]|System.debug(ANY)
21:57:11.029 (6029183847)|SYSTEM_METHOD_ENTRY|[352]|String.valueOf(Object)
21:57:11.029 (6029216859)|SYSTEM_METHOD_EXIT|[352]|String.valueOf(Object)
21:57:11.029 (6029232089)|SYSTEM_METHOD_ENTRY|[352]|System.debug(ANY)
21:57:11.029 (6029237392)|USER_DEBUG|[352]|DEBUG|Gad --> lst_tiersToDelete before: ()
21:57:11.029 (6029241814)|SYSTEM_METHOD_EXIT|[352]|System.debug(ANY)
21:57:11.029 (6029261326)|SYSTEM_METHOD_ENTRY|[354]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029288955)|SYSTEM_METHOD_EXIT|[354]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029305103)|SYSTEM_METHOD_ENTRY|[354]|Map<Decimal,Tier__c>.remove(Object)
21:57:11.029 (6029329327)|SYSTEM_METHOD_EXIT|[354]|Map<Decimal,Tier__c>.remove(Object)
21:57:11.029 (6029342760)|SYSTEM_METHOD_ENTRY|[354]|List<Tier__c>.add(Object)
21:57:11.029 (6029359781)|SYSTEM_METHOD_EXIT|[354]|List<Tier__c>.add(Object)
21:57:11.029 (6029378260)|SYSTEM_METHOD_ENTRY|[355]|Map<Id,Map<Decimal,Country_Rate__c>>.get(Object)
21:57:11.029 (6029405400)|SYSTEM_METHOD_EXIT|[355]|Map<Id,Map<Decimal,Country_Rate__c>>.get(Object)
21:57:11.029 (6029421065)|SYSTEM_METHOD_ENTRY|[355]|Map<Decimal,Country_Rate__c>.remove(Object)
21:57:11.029 (6029440147)|SYSTEM_METHOD_EXIT|[355]|Map<Decimal,Country_Rate__c>.remove(Object)
21:57:11.029 (6029452729)|SYSTEM_METHOD_ENTRY|[355]|List<Country_Rate__c>.add(Object)
21:57:11.029 (6029466602)|SYSTEM_METHOD_EXIT|[355]|List<Country_Rate__c>.add(Object)
21:57:11.029 (6029485126)|SYSTEM_METHOD_ENTRY|[356]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029512135)|SYSTEM_METHOD_EXIT|[356]|Map<Id,Map<Decimal,Tier__c>>.get(Object)
21:57:11.029 (6029526365)|SYSTEM_METHOD_ENTRY|[356]|Map<Decimal,Tier__c>.get(Object)
21:57:11.029 (6029549457)|SYSTEM_METHOD_EXIT|[356]|Map<Decimal,Tier__c>.get(Object)
21:57:11.029 (6029566591)|SYSTEM_METHOD_ENTRY|[356]|String.valueOf(Object)
21:57:11.029 (6029628506)|SYSTEM_METHOD_EXIT|[356]|String.valueOf(Object)
21:57:11.029 (6029644890)|SYSTEM_METHOD_ENTRY|[356]|System.debug(ANY)
21:57:11.029 (6029650390)|USER_DEBUG|[356]|DEBUG|Gad --> map_plIdToTiers.get(priceListId).get(i+1): Tier__c:{Id=a1Hm0000000HYvCEAW, RecordTypeId=012m00000000QuiAAE, Price_List__c=a0mm0000006xFhrAAE, Tier_Seq__c=3}
21:57:11.029 (6029656261)|SYSTEM_METHOD_EXIT|[356]|System.debug(ANY)
21:57:11.029 (6029681427)|SYSTEM_METHOD_ENTRY|[357]|String.valueOf(Object)
21:57:11.029 (6029711625)|SYSTEM_METHOD_EXIT|[357]|String.valueOf(Object)
21:57:11.029 (6029725969)|SYSTEM_METHOD_ENTRY|[357]|System.debug(ANY)
21:57:11.029 (6029731195)|USER_DEBUG|[357]|DEBUG|Gad --> lst_tiersToDelete after: (null)

Answer

Based on the test below, this appears to be a platform bug when key values are coerced (implicitly converted) to the declared type of the key. (At least for Decimal keys but may affect other types.) The first test method here fails and the second and third ones pass (and comply with the Map contract):

@isTest
private class MapTest {

    @isTest
    static void mixed() {
        Map<Decimal, String> m = new Map<Decimal, String>();
        m.put(8, 'Eight');
        System.assertEquals(true, m.containsKey(8));
        System.assertEquals('Eight', m.remove(8));
        System.assertEquals(false, m.containsKey(8));
    }

    @isTest
    static void decimal() {
        Map<Decimal, String> m = new Map<Decimal, String>();
        m.put(Decimal.valueOf(8), 'Eight');
        System.assertEquals(true, m.containsKey(Decimal.valueOf(8)));
        System.assertEquals('Eight', m.remove(Decimal.valueOf(8)));
        System.assertEquals(false, m.containsKey(Decimal.valueOf(8)));
    }

    @isTest
    static void integer() {
        Map<Integer, String> m = new Map<Integer, String>();
        m.put(8, 'Eight');
        System.assertEquals(true, m.containsKey(8));
        System.assertEquals('Eight', m.remove(8));
        System.assertEquals(false, m.containsKey(8));
    }
}

In e.g. Java a compile error would flag that 8 isn’t a BigDecimal and so block the problem at compile time.

So use Integer as the type for the key and make sure the values looked up are all Integer values (or be careful about the type conversion of the values used) as a work-around and raise a case with Salesforce about the bug.

Attribution
Source : Link , Question Author : Dagish , Answer Author : Keith C

Leave a Comment