javascript实现原生的Java版本的HashMap及LinkedHashMap
2013-06-03 11:36
711 查看
javascript实现原生的HashMap及LinkedHashMap
用面象对象的方式去使用javascript,性能比较差,但功能完善。
也许在使用javascript时,应该要更多的使用该语言本身的特性。
用面象对象的方式去使用javascript,性能比较差,但功能完善。
也许在使用javascript时,应该要更多的使用该语言本身的特性。
/** * email:collonn@126.com * QQ:195358385 */ var scriptjava = { log : { enable : false, consoleEnable : function() { return typeof console == 'undefined' ? false : true; }, info : function(message) { if (scriptjava.log.enable && scriptjava.log.consoleEnable()) { console.log(message); } else if(scriptjava.log.enable) { alert(message); } }, warn : function(message) { if (scriptjava.log.enable) { console.warn(message); } } }, util : {} } /* * null: return null '': return 0 */ scriptjava.util.hashCode = function(str) { var hash = 0; if (arguments.length == 0) { throw new Error('number of arguments must > 1'); } // null: return null '': return 0 if (str == null || str == '') { return hash; } // conver number to string if (typeof str == 'number') { str = new String(str); } for ( var i = 0; i < str.length; i++) { hash = 31 * hash + str.charCodeAt(i); } return hash; } /** * --------------------------- scriptjava.util.HashMap define start --------------------------- */ scriptjava.util.HashMap = function(configObj) { this._capacityDefault = 16; // config property default this._capacity = this._capacityDefault; this._loadFactor = 0.75; this._size = 0; this._maxLoop = 100; // config property custom if (arguments.length == 1 && typeof configObj == 'object') { for (property in configObj) { this['_' + property] = configObj[property]; } } // config property other this._maxSize = parseInt(this._capacity * this._loadFactor); this._table = new Array(this._capacity); } /* * the key-value element of HashMap this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype.Entry = function(key, value) { this.key = key, this.value = value, this.next = null } /* * this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype._createEntry = function(key, value){ return new this.Entry(key, value); } /* * this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype._addEntry = function(entry){ } /* * this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype._recordAccess = function(entry){ } /* * this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype._addEntry = function(entry){ } //Returns an Array of the keys contained in this map. scriptjava.util.HashMap.prototype.keySet = function(){ scriptjava.log.info('HashMap.keySet()...'); var keyAry = new Array(this._size); for ( var i = 0; i < this._table.length; i++) { if (this._table[i] == undefined) { continue; } var entryTemp = this._table[i]; while (entryTemp != null) { keyAry.push(entryTemp.key); entryTemp = entryTemp.next; } } return keyAry; } /* * Removes all of the mappings from this map. * The map will be empty after this call returns. */ scriptjava.util.HashMap.prototype.clear = function(key, value) { // for ( var i = 0; i < this._table.length; i++) { // delete this._table[i]; // } scriptjava.log.info('HashMap.clear()...'); this._capacity = this._capacityDefault; this._table = new Array(this._capacity); this._maxSize = parseInt(this._capacity * this._loadFactor); this._size = 0; if(this._head != undefined){ this._head = null; } if(this._tail != undefined){ this._tail = null; } } /* * 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. */ scriptjava.util.HashMap.prototype.put = function(key, value) { var returnEntry = null; var findByKey = false; // rebuild map when need if (this._size == this._maxSize) { scriptjava.log.warn('WARNNING, Map is nearly full, size:' + this._size + ', maxSize:' + this._maxSize + ', capacity:' + this._capacity); this._resize(); } var hash = this._reHash(scriptjava.util.hashCode(key)); var indexOfKey = this._indexFor(hash, this._capacity); scriptjava.log.info('Map.put(' + key + ',' + value + '),' + 'indexOfKey:' + indexOfKey); var entryNew = this._createEntry(key, value); returnEntry = entryNew; // put the new entry on the right index of table if (this._table[indexOfKey] == undefined) { this._table[indexOfKey] = entryNew; this._addEntry(entryNew); } else { // if key already exists, then update the value of this key var alreadyExists = false; var entryTemp = this._table[indexOfKey]; while (entryTemp != null) { if (entryTemp.key == key) { alreadyExists = true; findByKey = true; entryTemp.value = value; returnEntry = entryTemp; break; } else { entryTemp = entryTemp.next; } } if (!alreadyExists) { entryNew.next = this._table[indexOfKey]; this._table[indexOfKey] = entryNew; this._addEntry(entryNew); } } if (!findByKey) { this._size++; } //the put() opretion will add new or update value, so, will always execute this._recordAccess() if(this._accessOrderPut != undefined && this._accessOrderPut == true){ this._recordAccess(entryNew); } return returnEntry; } /* * this method will be overwrite by LinkedHashMap */ scriptjava.util.HashMap.prototype._removeEntry = function(entry){ } /* * Removes the mapping for the specified key from this map if present. */ scriptjava.util.HashMap.prototype.remove = function(key) { var returnEntry = null; var hash = this._reHash(scriptjava.util.hashCode(key)); var index = this._indexFor(hash, this._capacity); var findByKey = false; if (this._table[index] == undefined) { return null; } else { var entryTemp = this._table[index]; var entryTempPre = null; while (entryTemp != null) { if (entryTemp.key == key) { findByKey = true; returnEntry = entryTemp; if (entryTempPre == null && entryTemp.next == null) { // only one entry in this entryList delete this._table[index]; } else if (entryTempPre == null && entryTemp.next != null) { // at least 2 entry in this entryList, and, is the head this._table[index] = entryTemp.next; } else if (entryTempPre != null && entryTemp.next == null) { // at least 2 entry in this entryList, and, is the tail entryTempPre.next = null; } else { // at least 3 entry in this entryList, and, is the middle entryTempPre.next = entryTemp.next; } scriptjava.log.info('Map.romove(' + key + '), value:' + (returnEntry == null ? null : returnEntry.value)); this._removeEntry(entryTemp); break; } entryTempPre = entryTemp; entryTemp = entryTemp.next; } } if (findByKey) { this._size--; } return returnEntry; } /* * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. */ scriptjava.util.HashMap.prototype.get = function(key) { var hash = this._reHash(scriptjava.util.hashCode(key)); var index = this._indexFor(hash, this._capacity); if (this._table[index] == undefined) { return null; } else { var i = 0; var valueFinal = null; var entryTemp = this._table[index]; while (entryTemp != null) { i++; if (i > this._maxLoop) { break; scriptjava.log.warn('too mach loops, performents will be down:' + i); } if (entryTemp.key == key) { valueFinal = entryTemp.value; scriptjava.log.info('Map.get(' + key + '),' + 'value:' + valueFinal + ',loops:' + i); this._recordAccess(entryTemp); break; } else { entryTemp = entryTemp.next; } } return valueFinal; } } /* * Returns true if this map contains a mapping for the specified key. */ scriptjava.util.HashMap.prototype.containsKey = function(key) { var hash = this._reHash(scriptjava.util.hashCode(key)); var index = this._indexFor(hash, this._capacity); var contains = false; if (this._table[index] == undefined) { scriptjava.log.info('Map.containsKey(' + key + '), ' + contains); return contains; } var entryTemp = this._table[index]; while (entryTemp != null) { if (entryTemp.key == key) { contains = true; break; } else { entryTemp = entryTemp.next; } } scriptjava.log.info('Map.containsKey(' + key + '), ' + contains); return contains; } /* * for each element of hashmap, call an costom function */ scriptjava.util.HashMap.prototype.foreach = function(foreachFun) { scriptjava.log.info('HashMap.foreach() start..............'); for ( var i = 0; i < this._table.length; i++) { if (this._table[i] == undefined) { continue; } var entryTemp = this._table[i]; while (entryTemp != null) { foreachFun(entryTemp); entryTemp = entryTemp.next; } } scriptjava.log.info('HashMap.foreach() enddd..............'); } /* * Returns the number of key-value mappings in this map. */ scriptjava.util.HashMap.prototype.size = function() { scriptjava.log.info('Map.size(),' + this._size); return this._size; } /* * Returns true if this map contains a mapping for the specified key. */ scriptjava.util.HashMap.prototype.isEmpty = function() { return this._size == 0 ? true : false; } /* * Rehashes the contents of this map into a new array with a larger capacity. This method is called automatically when the number of keys in this map * reaches its threshold. */ scriptjava.util.HashMap.prototype._resize = function() { var capacityNew = this._capacity * 2; var maxSizeNew = parseInt(capacityNew * this._loadFactor); var tableNew = new Array(capacityNew); scriptjava.log.info('rebuild map,_capacity:' + capacityNew); scriptjava.log.info('rebuild map,_loadFactor:' + this._loadFactor); scriptjava.log.info('rebuild map,_maxSize:' + maxSizeNew); for ( var i = 0; i < this._table.length; i++) { if (this._table[i] == undefined) { continue; } var entryTemp = this._table[i]; while (entryTemp != null) { var hash = this._reHash(scriptjava.util.hashCode(entryTemp.key)); var indexOfKey = this._indexFor(hash, capacityNew); scriptjava.log.info('rebuild map, key:' + entryTemp.key + ', value:' + entryTemp.value + ', indexOfKey:' + indexOfKey); var entryNew = new this.Entry(entryTemp.key, entryTemp.value, null); // put the new entry on the right index of table if (tableNew[indexOfKey] == undefined) { tableNew[indexOfKey] = entryNew; } else { entryNew.next = tableNew[indexOfKey]; tableNew[indexOfKey] = entryNew; } entryTemp = entryTemp.next; } } this._capacity = capacityNew; this._maxSize = maxSizeNew; this._table = tableNew; } scriptjava.util.HashMap.prototype._reHash = function(h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } scriptjava.util.HashMap.prototype._indexFor = function(h, length) { return h & (length - 1); } /** * --------------------------- scriptjava.util.HashMap define enddd --------------------------- */ /** * --------------------------- scriptjava.util.LinkedHashMap define start --------------------------- */ scriptjava.util.LinkedHashMap = function(configObj){ //extends from scriptjava.util.HashMap scriptjava.util.HashMap.call(this); this._head = null; this._tail = null; //when true, the get() method will influce the access order this._accessOrder = false; //when true, the put() method will influce the access order alse, but it always be false this._accessOrderPut = false; // config property custom if (arguments.length == 1 && typeof configObj == 'object') { for (property in configObj) { this['_' + property] = configObj[property]; } } } //extends from scriptjava.util.HashMap scriptjava.util.LinkedHashMap.prototype = new scriptjava.util.HashMap(); scriptjava.util.LinkedHashMap.prototype.constructor = scriptjava.util.LinkedHashMap; // overwrite Entry scriptjava.util.LinkedHashMap.prototype.Entry = function(key, value) { this.key = key, this.value = value, this.next = null, this.before = null, this.after = null, this.count = 0; } // overwrite _createEntry() scriptjava.util.LinkedHashMap.prototype._createEntry = function(key, value){ return new this.Entry(key, value); } // overwrite _addEntry(), add an entry to the linkedlist tail scriptjava.util.LinkedHashMap.prototype._addEntry = function(entry){ if(this._head == null && this._tail == null){ this._head = entry; this._tail = entry; }else{ entry.before = this._tail; this._tail.after = entry; this._tail = entry; } } /* * remove an element from linkedlist */ scriptjava.util.LinkedHashMap.prototype._removeEntry = function(entry){ if(entry == this._head && entry.after == null){// only one entry this._head = null; this._tail = null; }else if(entry == this._head && entry.after != null){// at least two entry, and, the head this._head = entry.after; }else if(entry == this._tail){// at least two entry, and, the tail entry.before.after = null; this._tail = entry.before; }else{//at least three entry, and, the middle entry.before.after = entry.after; this._tail = entry.after; } } // overwrite _createEntry() scriptjava.util.LinkedHashMap.prototype._recordAccess = function(entry){ if(!this._accessOrder){ return; } //linkedlist is empty if(this._head == null && this._tail == null){ this._head = entry; this._tail = entry; return; } if(entry == this._head){ return; } //the last one of linkedlist if(entry == this._tail && entry != this._head){ entry.before.after = entry.after; this._tail = entry.before; entry.before = null; entry.after = this._head; this._head.before = entry; this._head = entry; return; } //middle of the linkedlist if(entry != this._head && entry != this._tail){ entry.before.after = entry.after; entry.after.before = entry.before; entry.after = this._head; entry.before = null; this._head.before = entry; this._head = entry; return; } } // overwrite _addEntry() scriptjava.util.LinkedHashMap.prototype.foreach = function(foreachFun){ scriptjava.log.info('LinkedHashMap.foreach() start...'); var tempEntry = this._head; while(tempEntry != null){ foreachFun(tempEntry); tempEntry = tempEntry.after; } scriptjava.log.info('LinkedHashMap.foreach() enddd...'); } /** * --------------------------- scriptjava.util.LinkedHashMap define enddd --------------------------- */ /** * --------------------------- scriptjava.util.ArrayList define Start --------------------------- */ scriptjava.util.ArrayList = function(configObj){ this._capacityDefault= 16; // config property default this._capacity = this._capacityDefault; this._size = 0; // config property custom if (arguments.length == 1 && typeof configObj == 'object') { for (property in configObj) { this['_' + property] = configObj[property]; } } } /** * --------------------------- scriptjava.util.ArrayList define enddd --------------------------- */
相关文章推荐
- (11) java集合 ---- LinkedHashMap和HashMap等Map的比较使用以及 LinkedHashMap的实现原理
- java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类HashMap Hashtable LinkedHashMap 和TreeMap.
- javascript实现java中的HashMap的功能
- Map映射—Java实现—LinkedHashMap、HashMap、TreeMap
- 用 JavaScript 实现类似 Java 的 HashMap 对象
- java中HashMap,LinkedHashMap,TreeMap,HashTable,ConcurrentHashMap的区别和内部实现机制
- Javascript实现Java的HashMap(链表散列)
- (java面试)Map接口的四个实现:HashMap,HashTable,TreeMap,LinkedHashMap异同
- Android中Java和JavaScript交互 Android原生和html交互
- 文本分类算法之--贝叶斯分类算法的实现Java版本
- (转)java学习:HashMap的实现原理
- 亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本
- Java中HashMap的实现原理
- 原生javascript实现无间缝滚动示例
- 原生javascript实现图片无缝滚动效果
- java面试之HashMap的实现原理和底层数据结构
- 一个简单的一致性哈希算法实现(Java版本)
- Java HashMap实现原理1——散列表
- java 基于linkedhashmap实现LRUCache
- javascript原生代码实现ajax请求