Add additional key, value pair into map object

apexmap

I'm trying to write key, value entries to a map object however, it looks like the first key, value pair is being overwritten by the second. Code looks like this:

trigger AccountChangeTrigger on Account (after update, after insert, after delete, after undelete) {

    // Serialize records to JSON string
    String oldRecord = JSON.serialize(Trigger.old);
    String newRecord = JSON.serialize(Trigger.new);

    // Create mapObject
    Map<String, String> mapObject = new Map<String, String>();
    mapObject.put('Old Record', oldRecord);
    mapObject.put('New Record', newRecord);

}

(oldRecord and newRecord here are just Trigger.old and Trigger.new values.)

I'm coming from a dynamic programming language background (python) and I guess that Apex doesn't share the same structure of a map/dictionary as a dynamic language. Seems as though put() method is overwriting the first entry. So how can I add additional key, value pair into this map object?

I've used the code in this example here but it hasn't worked as expected.

Best Answer

tl;dr

This is just an artifact of the data you're using and how you've chosen to write it to the debug log.

longer version

As the comments have noted, the Map collection type in Apex behaves pretty much exactly the same as a Map/Dictionary does in any other language (a language being statically vs dynamically typed really doesn't matter here).

  • If you .put() into a map, and that key doesn't yet exist, the key and value are added to the map
  • If you .put() into a map, and the key you use does exist, the value stored by the key is overwritten

Also as noted in the comments, System.debug() only provides limited output. It'll stop printing data to the debug log after some ill-defined point, truncating it unceremoneously. Under certain circumstances, it can appear that data is missing or being overwritten, but that's not what's actually happening. The data is still there, you just can't view all of it at once using a single System.debug().

If you want to make sure that you see at least a little bit of data for every item in a collection (a List, Set, or Map), then you should loop over the collection one item at a time, and System.debug() individual items.

Following your example, that'd be

// If you want/need both the key and the value of a map, you'll need to iterate over the keys
// As the method name indicates, keySet() gives you the Set of keys contained by the map
//   (a Set<String> in your case, matching the key type defined for your map)
for(String mapKey :mapObject.keySet()){
    system.debug(String.format('Key: {0}, Value = {1}', new List<Object>{
        mapKey, mapObject.get(mapKey)
    });
}

Note that while you will see some data for each map key, the serialized data for a single SObject instance coming from a Trigger Context Variable is still quite long and liable to itself be truncated. Even moreso considering you're trying to serialize the entirety of Trigger.new and Trigger.old instead of a single record from each.

In the end, if you want to guarantee that certain data is output to the log, you should use individual System.debug() calls. Iterate over collections, and debug every field you're interested in.

Related Topic