MAP.keys() method doens t work as before (F945 2.7 firmware, F645Music 5.9 firmware)

This is a map defined in a resources.xml file

<jsonData id="jsonIndexMap">{
        "0":5, "1":9, "2":13, "3":17, "4":21, "5":25, "6":29 , "7":33
 }</jsonData>

Code to highlight the issue

var indexMap = WatchUi.loadResource(Rez.JsonData.jsonIndexMap);
var keys = indexMap.keys();
var keyString = "";
var valueString= "";
for (var j = 0; j < keys.size(); j++) {
       var ind = keys[j];
       keyString = keyString + ind + "-";
       valueString= valueString+ indexMap.get(ind) + ".";
  }

RESULT, for the simulator and all devices and  f945 before firmware 2.7 and f645Music before firmware 5.9

Sys.println(keyString);     ->0-1-2-3-4-5-6-7-

Sys.println(valueString); ->5-9-13-17-21-25-29-33-

New behaviour for F945 2.7 and F645Music 5.9

Sys.println(keyString);     ->6-7-0-1-2-3-4-5-

Sys.println(valueString); ->29-33-5-9-13-17-21-25-

It s big issue for me.

  • I think this is something that you really couldn't count on before. Maybe change your logic to build valueString in a sorted order based on keyString?

    Or if the keys are always something like 0 to 9, use that as the index into the valueString array

  • Absolutely, I will change that, but something has changed Garmin side.

    Assuming that the Map.key() method implementation has changed is not apparent, this is not an easy bug to find, more over the issue is only on real devices with specific firmware.

  • I'm not sure something has changed, as I know in the case where I get JSON data by way of a makeWebRequest, when I prlntln the data, the order isn't always the same when running on a watch. You may have just been lucky before, 

  • I am a bit confused with that, a map is sorted by keys, that s why map is fast, it can t ordered in a random way.

    Are you sure the keys of your map are the same? the order should be set according to a "comparator", a hashcode for an object, string comparison for strings, number comparison for numbers....

    Moreover when I put the sample in my watch the order is always the same, in my mind it s normal, the algorythm which set keys in a map cant give different results from the same value of key. And I assume the map "toString()" loops over keys in the same order that they are store in the map memory.

  • The implementation of Dictionary.keys() has not changed. The Dictionary is a hash collection and makes no guarantee about the order of the elements maintained within the collection (like Java's HashMap collection). This is explicitly documented in the class reference:

    Due to the nature of hash tables, the order of Dictionary elements are not guaranteed to match the insertion order.

    We made some changes to Dictionary that affected the initial size and the growth rate. These may have had an impact on the ordering of the elements in the collection (if a resize occurred with the new implementation that didn't occur with the old implementation), but again, we make no guarantees about the order of the elements.

    Additionally, a map (or our Dictionary) is not necessarily sorted by keys. One trivial implementation uses an array of buckets (linked lists typically), and when inserting a new item into the map the appropriate bucket to take the new key/value pair is determined by the *hash* of the key modulo the size of the array. i.e., assuming you use integers for keys, the hash function is identity, and the number of linked lists is 11 (indexed 0 to 10), inserting a key/value pair with key=1 may get inserted into bucket 1, but a value with key=11 would get inserted into bucket 0.

  • I have changed the way to use my map, no more problem now,.

    No,  keys are strings in my case.

    Anyway I have my answer, my code was not very good and the modifications made to Dictionnary has lead to a bug for my app (not eqsy to find).

    Thank you Travis.

  • No problem. Sorry to have exposed that bug in your code.