var Hashtable = (function() {
	var prefix = ' $';
	function isNull(object) {return !object && ('object' == typeof object);}
	function isNumber(object) {return 'number' == typeof object;}
	function isUndefined(object) {return 'undefined' == typeof object;}
	function Element(key, value) {
		this.key = key;
		this.value = value;
		this.next = null;
	}
	function Hashtable() {
		var table = {data : []},
		    entries = 0;

		this.get = function(key) {var index, tableData = table.data;
			if(!isNull(key) && !isUndefined(key)
			 && isNumber(index = table[prefix + key]))
			{
				var node = tableData[index];
				while(node && (node.key !== key)) {node = node.next;}
				if(node) {return node.value;}
			}
		};
		this.put = function(key, value) {var index, prefixedKey, tableData = table.data;
			if(isNull(key) || isUndefined(key) || isUndefined(value)) {return;}
			if(isNumber(index = table[prefixedKey = prefix + key])) {
				var node = tableData[index], previousNode = null;
				while(node && (node.key !== key)) {
					previousNode = node;
					node = node.next;
				}
				if(node) {
					var oldValue = node.value;
					node.value = value;
					return oldValue;
				} else {
					previousNode.next = new Element(key, value);
				}
			}
			else {
				table[prefixedKey] = tableData.length;
				tableData[tableData.length] = new Element(key, value);
			}
			++entries;
		};
		this.remove = function(key) {var index, prefixedKey, tableData = table.data;
			if(!isNull(key) && !isUndefined(key)
			 && isNumber(index = table[prefixedKey = prefix + key]))
			{
				var node = tableData[index], previousNode = null, returnValue;
				while(node && (node.key !== key)) {
					previousNode = node;
					node = node.next;
				}
				if(!node) {return;}
				returnValue = node.value;
				if(previousNode) {previousNode.next = node.next;}
				else {tableData[index] = node.next;}
				if(!tableData[index]) {
					for(var length = tableData.length - 1; index < length; ++index) {
						tableData[index] = tableData[index + 1];
						--table[prefix + tableData[index].key];
					}
					delete tableData[index];
					delete table[prefixedKey];
				}
				--entries;
				return returnValue;
			}
		};
	}
	Hashtable.prototype.containsKey = function(key) {
		return !isUndefined(this.get(key));
	};
	return Hashtable;
})();
