Posted on 2007-10-12 11:46
Kerwin Weng 閱讀(3544)
評(píng)論(2) 編輯 收藏 所屬分類:
Javascript
最近寫AJAX的應(yīng)用遇到很多需要豐富的Javascript集合的地方,可惜javascript沒有Java的Collection那么強(qiáng)大的集合類,于是打算自己嘗試寫一個(gè)模擬Set的API,結(jié)果寫出來的模擬類和Set有點(diǎn)不同,有一個(gè)優(yōu)勢--可以有序取單個(gè)對(duì)象,但也有一個(gè)劣勢,就是刪除單個(gè)對(duì)象需要遍歷該集合,由于我的應(yīng)用不大可能用到單個(gè)刪除,所以我暫時(shí)還沒有想到一種數(shù)據(jù)結(jié)構(gòu)可以實(shí)現(xiàn)不遍歷的單個(gè)對(duì)象刪除,又能滿足現(xiàn)有的API都高效完成,如果誰有更好的代碼來實(shí)現(xiàn)請(qǐng)回復(fù)
目前想到可以實(shí)現(xiàn)的方法:
add(o);
addAll(array)
contain(o);
get(int);
getAll();
sort(comparator); //傳進(jìn)去的是一個(gè)fn,還沒有寫例子....
size();
remove();
reverse();
基本數(shù)據(jù)結(jié)構(gòu)是兩個(gè)數(shù)組,一個(gè)是index數(shù)組,數(shù)組下標(biāo)連續(xù),用來存放第二個(gè)數(shù)組的下標(biāo),另一個(gè)是存放對(duì)象的數(shù)組,不連續(xù),下標(biāo)是對(duì)象的id或者對(duì)象中其他任何可以轉(zhuǎn)換成唯一Integer的Field(Set也要求放進(jìn)去的對(duì)象必須要有hashCode嘛,不然沒法區(qū)別第一個(gè)和第二個(gè))
實(shí)現(xiàn)的API:
function Collection(){
this.chain=new Array();
this.table=new Array();
}
Collection.prototype.get=function(i){
return this.table[this.chain[i]];
}
Collection.prototype.add=function(o){
this.table[o.id]=o;
this.chain.push(o.id);
}
Collection.prototype.addAll=function(array){
for(var _i=0;_i<array.length;_i++){
this.add(array[_i]);
}
}
Collection.prototype.contain=function(o){
if(this.table[o.id]){
return true;
}else{
return false;
}
}
Collection.prototype.getAll=function(){
tempList=new Array();
for(var _i=0;_i<this.chain.length;_i++){
tempList.push(this.table[this.chain[_i]]);
}
return tempList;
}
Collection.prototype.sort=function(comparator){
this.chain.sort(comparator);
}
Collection.prototype.remove=function(o){
var _var = this.chain;
for(var _i=0;i<this.chain.length;i++){
if(this.table[this.chain[_i]].id==o.id){
this.table[this.chain[_i]]=null;
this.chain.splice(_i,1);
return;
}
}
}
Collection.prototype.size=function(){
return this.chain.length;
}
Collection.prototype.reverse=function(){
this.chain.reverse();
}
目前還有一個(gè)addAll方法也是暫時(shí)沒有想到有什么不用遍歷的好的實(shí)現(xiàn)
前同事提供了一種完全和Set一樣的實(shí)現(xiàn),效率滿高
function Map(){
this.obj = {};
this.count = 0;
}
Map.prototype.put = function(key, value){
var oldValue = this.obj[key];
if(oldValue == undefined){
this.count++;
}
this.obj[key] = value;
return oldValue;
}
Map.prototype.get = function(key){
return this.obj[key];
}
Map.prototype.remove = function(key){
var oldValue = this.obj[key];
if(oldValue != undefined){
this.count--;
delete this.obj[key];
}
return oldValue;
}
Map.prototype.size = function(){
return this.count;
}
function Set(getKey){
this.map = new Map();
this.getKey = getKey;
}
Set.prototype.add = function(value){
var key = this.getKey(value);
this.map.put(key, value);
}
Set.prototype.remove = function(value){
var key = this.getKey(value);
this.map.remove(key);
}
Set.protorype.getAll=function(){
tempArray=new Array();
for(var i in this.obj){
tempArray.push(i);
}
return tempArray;
}
Set.prototype.size = function(){
return this.map.size();
}
還有一個(gè)朋友的實(shí)現(xiàn)和我最初的差不多,但是remove方法相當(dāng)有創(chuàng)意,用正則表達(dá)式來刪除
Collection.prototype.remove=function(o){
var _var = this.chain;
this.table[o.id]=null;
var re = new RegExp("(^["+o.id+"]$)|(^["+o.id+"][,])|([,]["+o.id+"]$)","g");
var s = "["+this.chain.toString().replace(re,"").replace(","+o.id+",",",")+"]";
this.chain=eval(s)
}
有人回復(fù)說需要添加做驗(yàn)證,我覺得不必了,如果添加的值和之前的一樣就直接替換好了,如果希望不被replace,直接在添加新對(duì)象之前用contain判斷一次就可以了,畢竟在我的實(shí)現(xiàn)中已不是完全在模擬Set了,目前更傾向于設(shè)計(jì)一個(gè)更高效和強(qiáng)大的集合類