A JavaScript Implementation of java.util.Map
Posted on Jun 2, 2014 (last modified May 8, 2021)
As a Java developer, I use a lot of maps – especially instances of HashMap. A map is a dictionary or lookup table that contains key/value pairs. It provides a very convenient way to cache objects for easy retrieval by some identifier such as a string (the key). It’s so convenient, in fact, that I find myself struggling without a JavaScript equivalent, so I wrote one. Following is a partial JavaScript implementation of the java.util.Map interface, which you are free to copy and use.
JavaScript Map usage example
As you can see from the example below, using this map is just like using a map in Java.
var myMap = new Map();
myMap.put('myKey1',"Hello World!");
myMap.put('myKey2',{'prop1':'How','prop2':' are you?'});
console.log( myMap.get('myKey1') );
console.log( myMap.get('myKey2').prop1 + myMap.get('myKey2').prop2);
JavaScript Map
* An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
* For those familiar with the Java programming language, this is similar to a HashMap; it implements most of the
* methods defined by Java's java.util.Map interface.
*
* @constructor
* @version 1.1.0
* @author cody@base22.com Burleson, Cody
*/
function Map() {
this.dict = {};
/**
* Returns the number of key-value mappings in this map.
* @method
*/
this.size = function() {
return Object.keys(this.dict).length;
};
/**
* Returns true if this map contains no key-value mappings.
* @method
*/
this.isEmpty = function() {
return Object.keys(this.dict).length == 0;
};
/**
* Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
* @method
*/
this.get = function(key){
return this.dict[key];
};
/**
* Returns true if this map contains a mapping for the specified key.
* @method
*/
this.containsKey = function(key){
if( this.get(key) !== undefined) {
return true;
} else {
return false;
}
};
/**
* Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
* @method
*/
this.put = function(key,value) {
this.dict[key] = value;
};
/**
* Removes the mapping for the specified key from this map if present.
* @method
*/
this.remove = function(key) {
'use strict';
delete this.dict[key];
};
/**
* Removes all of the mappings from this map. The map will be empty after this call returns.
* @method
*/
this.clear = function(){
this.dict = {};
};
/**
* Executes the given callback for each entry in this map until all entries have been processed.
* The given callback will be passed a map entry as parameter. So, for example...
*
* function myCallback(mapEntryItem) {
* console.log('I will process this item: ' + mapEntryItem.text);
* }
*
* myMap.forEach(myCallback);
*
* @method
*/
this.forEach = function(callback) {
var len = this.size();
for (i = 0; i < len; i++) {
var item = this.get( Object.keys(this.dict)[i] );
callback(item);
}
}
}
Test Class
/**
* =============================
* Map Test Cases
* =============================
*/
/**
* Useful for unit testing JavaScript, this method asserts that the given condition is true.
* If the given condition is not true, an optionally provided message is logged or 'Assertion failed.'
* @method
*/
function assert(condition, message) {
if (!condition) {
console.error(message) || console.error('Assertion failed');
} else {
console.log("-- PASS");
}
}
// Instantiate a new Dictionary object...
var myMap = new Map();
// Test that isEmpty returns true at this point
assert( myMap.isEmpty() );
// Test that size is zero at this point
assert( myMap.size() == 0 , "size should be zero before any entries have been put into the lookup table.");
// Put a sim0le string value in the dictionary and then test for it
myMap.put('key1','http://value1?dt=2014_06_01&dummy=true');
// Now let's test adding a different kind of object...
var testObj = {prop1:"Hello", prop2:" World!"};
myMap.put('key2',testObj);
// Test that size now equals one
assert( myMap.size() == 2, "size should be 2 after adding 2 entries.");
var ref = myMap.get('key2');
// Test that ref was fetched from the dictionary
assert( ref !== undefined , "ref should not be undefined; it should be a reference to testObj");
// Test a property of the fetched object; just to show there is support for more than just string types
assert( ref.prop1 == 'Hello' , "ref.prop1 should equal 'hello' ");
// Show that containsKey is false when there is no matching key
assert( myMap.containsKey('notReal') == false, "containsKey('notReal') should return false; no such object is in the lookup table.");
// Show that containsKey is true when there is a matching object found
assert( myMap.containsKey('key2') == true, "containsKey('key2') should return true; that object is in the lookup table.");
// Now, we remove an item to test the remove() method
myMap.remove('key1');
assert( myMap.size() == 1 , "size should be 1 after removing item under 'key1'.");
// Finally, test the clear()
myMap.clear();
assert( myMap.size() == 0 , "size should be 0 after clearing lookup table.");
JavaScript Map API
Map
new Map()
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. For those familiar with the Java programming language, this is similar to a HashMap; it implements most of the methods defined by Java’s java.util.Map
interface.
Methods
clear()
Removes all of the mappings from this map. The map will be empty after this call returns.
containsKey(key)
Returns true if this map contains a mapping for the specified key. Parameters:
Name | Type | Description |
---|---|---|
key | String | key whose presence in this map is to be tested |
forEach(callback)
Executes the given callback for each entry in this map until all entries have been processed. The given callback will be passed a map entry as parameter. So, for example…
function myCallback(mapEntryItem) {
console.log('I will process this item: ' + mapEntryItem.text);
}
myMap.forEach(myCallback);
Parameters:
Name | Type | Description |
---|---|---|
callback | function | The callback function that will be called for each entry in the map and which will be passed the value for each entry in the map. |
isEmpty()
Returns true if this map contains no key-value mappings.
put(key, value)
Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
Name | Type | Description |
---|---|---|
key | String | key with which the specified value is to be associated |
value | Object | value to be associated with the specified key |
remove(key)
Removes the mapping for the specified key from this map if present.
Name | Type | Description |
---|---|---|
key | String | key whose mapping is to be removed from the map |
size()
Returns the number of key-value mappings in this map.
Gist on GitHub
https://gist.github.com/codyburleson/089157ed8eca114da8c4#file-javascript-map