The inclusion of the Dictionary class in ActionScript 3 creates numerous possibilities when sub classing. The Dictionary class allows for creating key / value mappings or tables which are more commonly known as Hashes or Hash Maps. The only problem is that the Dictionary class does not provide an API for working with the map. The Dictionary class is a good starting point in which sub classes can create managed key / value hash maps and provide methods for retrieving values and keys as well as removing values, determining how many key / values exist and so on.
I am working on a project in which the data set is comprised of sentences tokenized into their individual parts of speech; noun, verb, preposition etc. Part of the requirement is that a lookup can be made on any individual part of speech to retrieve further information such as tense, plurality and so on. At first I simply used a Dictionary for the mappings but ended up adding all kinds of logic outside of the map whenever I needed to check for a key or add a value and so on. So I decided to write a simple HashMap class for AS3 which is similar to the HashMap available in java.util.HashMap.
Below is an example of how to use the HashMap class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import com.ericfeminella.collections.IMap; import com.ericfeminella.collections.HashMap; var map:HashMap = new HashMap(); var o:Object = {name: "HashMap Example"}; map.put('name', o); trace(map.containsKey('name')); //true trace(map.containsValue(o)); //true trace(map.size()); //1 trace(map.getValue('name')); //[Object object] trace(map.isEmpty()); //false map.clear(); trace(map.containsKey('name')); //false trace(map.containsValue(o)); //false trace(map.size()); //0 trace(map.getValue('name')); //false trace(map.isEmpty()); //true |
You can view the source for the HashMap class as well as the IMap interface which defines the methods necessary for working with the HashMap.
Thx. Really usefull. Strange that this isn’t in Flex SDK. Lieven Cardoen, IndieGroup, Belguim
I have smal issue with hashp map,
if I do myHashMap.remove(“abc”);
it removes the value but leaves the key its not even nulling it, it is extremly strange because when I do:
Alert(myHashMap.size()); // returns 2)
myHashMap.remove(“abc”);/
Alert(myHashMap.size()); // returns 1) so it sounds like it removes it
but in :
for each ( var myObj:MyValueObject in myHashMap){
myObj.mymethod // throws Null Pointer Exception
}
after I debug I see following inside myHashMap
it has two keys but one of the keys value is null.what am I doing wrong?
Strange, make sure that you are using the latest version:
http://code.ericfeminella.com/classes/as3/HashMap.as.html
There was an issue in the original version whereas the values were being set to null rather than deleted. I have since updated the HashMap API to delete items completely, thus removing them from the instance. Give the updated version a try and let me know if this fixes the issue.
Thanks,
Eric
I got the utils.swc from here,about 3 weeks ago probably it was wrong version. anyways I just grabbed source now and build it from source to make sure , I will test delete, (I had to modify code to not use remove so I will go back and try with remove again)
I have also added one api Method – I needed “putAll” (not sure if its any use but will paste it here anyways )
/**
*
* Adds (appends) a hashMap contend to *this* existing HashMap
* if Null or HashMap size of 0 is passed it does nothing
* NOTE: Order of Apended HashMap content is not predictable.
*
* @param the HashMap to add to this HashMap
* @param the forceUpdate Boolean to force it to override
* value in *This* Object,if key for that value, matches with key of parameter HashMap.
* @return Number of Items added to the HashMap
*/
public function putAll(_newMap:IMap, _forceUpdate:Boolean=false) : int {
var _counter:int=0;
if(_newMap!==null && _newMap.size()>0){
for (var prop:String in _newMap) {
if (!this.containsKey(prop) || _forceUpdate){
this[prop] = _newMap[prop];
_counter++;
}
}
}
return _counter;
}
something wrong, There is a strange bug somewhere, I have a case that I add two items to hashtable following way
this.defaultRoleRegistry = new HashMap();
this.defaultRoleRegistry.put(“public”, new Role(“public”,-1));
this.defaultRoleRegistry.put(“system”, new Role(“system”,-999));
then I run right after that :
Alert.show(defaultRoleRegistry.size()+”
further investigations
while for each does not work(strange it used to work before).
but if I loop this way (it works)
Alert.show(defaultRoleRegistry.size()+”
As I had mentioned in a previous post I have refactored the HashMap API from an “is-a” relationship to a “has-a” relationship in order to provide security to the map from unintentional misuse.
Therefore you can only access the underlying map (Dictionary) in a HashMap instance via the operations defined in the IMap interface, which is implemented by the HashMap.
For more details please see:
http://www.ericfeminella.com/blog/2007/09/11/as3-hashmap-update/
Thanks,
Eric
NOTE:: changing API from IS a to Has a introduced small inconvenience, problem is that now hashmap is impossible to debug, because it has no public properties, and debugger cant read methods, I would say changing getKeys api method (in IMAP) to function get keys and getValues method to function get values will take care of the problem, otherwise cant debug hashmap.
This is not true, any object and all of it’s members can be debugged in Flex, otherwise it woulf kind of defeat the purpose of debugging.
What you need to do is enable “Show inaccessible Member Variables” in the Flex Debugging perspective in order to see them.
To do so simple go into the Flex Builder Debug perspective, in the top right hand corner select the arrow icon (the 3rd from last icon) select Flex and then check “Show inaccessible Member Variables”.
That’s it. Now debug as needed.
nice tip,it does show internal map variable now, I never thought that option would be buried there, I guess thats also default in java debugger,
Additional explanation: The code above is basically the same HashMap, but it is bindable. You will need it i.e. if you want bind GUI components to the HashMap.
Nice post. I was about to implement my own HashMap from the Dictionary until i found this. Thanks for saving me some work!
Good Morning,
Thank you very much for those classes, they are very helpful.
What I want know is how I can iterate on the map?
Thank you again.
Hello,
Now it’s fine, I iterate on my Map,
Thanks.. As Tim said : ” I was about to implement my own HashMap from the Dictionary until i found this. Thanks for saving me some work!”
is it woks with flex3 as I am getting some error for ‘IHashMapEntry’
You also need to get the following files:
http://code.ericfeminella.com/classes/as3/HashMapEntry.as.html
http://code.ericfeminella.com/classes/as3/IHashMapEntry.as.html
I’m using Flasch cs4 (still haven’t switched to Flex or flashdevelop). anyway, I downloaded and began implementing your collections package…It turns out that Flash (at least for me) does not have the mx.collections.IList class that you import in the IMap interface… i decided to see what would happen if i just commented out the import (terrible i know..but i really didn’t want to reinvent the hashmap wheel )… from some experiments so far, I seem to be able to use the classes without mx.collections.IList — i have been able to set, get, nadremove keys and values without any problems yet.
If you go to the page you can always find the latest versions of all OS APIs I have published. The latest versions of the HashMap API do not contain any references to Flex framework components.
Yea I seem to be having the same issue as e9. Wants the mx.collections.IList in the IMap class/interface. This is cause it imports it at the top and I guess this is really used for Flex and not just ordinrary as3 in Flash… Any chance of using it without the IList Class?
Let me know as I’d love to be using your work… keep it up!
Nick.
Great addition to flex libraries!
One comment – I would change implementation of the HashMap.isEmpty() so it does not call size() method – after all there is no need to iterate over each element to identify that it is empty. I would Implement it like this:
public function isEmpty() : Boolean
{
for (var key:* in map)
{
return false;
}
return true;
}
Can i bind the Java HashMap to Flex HashMap.as using [Bindable] [RemoteClass=…]?
Thanks
Prakash
I tried to use Hashmap but it gives the following error
1046: Type was not found or was not a compile-time constant: IHashMapEntry.
Can anybody help me with as I’m a newbie to flex
Hey Anantha,
The HashMap class has a direct dependency on the IHashMapEntry interface, therefore when using the Hashmap API you will need the dependencies as well, all of which can be found at:
Hi Eric,
First, I want to thank you for such a good HashMap class. Even though we have such a nice HashMap class, we cannot bind it to the Java HashMap. is there a tutorial/link to an article where I can learn about the assemblers to convert the Java HashMap to your Actionscript HashMap.
Tanx for saving my time! Great job!
TypeError: Error #1034: Type Coercion failed: cannot convert flash.utils::Dictionary@1e2727c1 to HashMap.
Casting between a Dictionary and HashMap doesn’t seem to work :(. Any solutions?