Habitat Framework

专注于Java EE企业级开发
posts - 13, comments - 81, trackbacks - 0, articles - 5
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

用Javascript模拟Java的Set

Posted on 2007-10-12 11:46 Kerwin Weng 阅读(3525) 评论(2)  编辑  收藏 所属分类: Javascript
最近写AJAX的应用遇到很多需要丰富的Javascript集合的地方,可惜javascript没有Java的Collection那么强大的集合类,于是打算自己尝试写一个模拟Set的API,结果写出来的模拟类和Set有点不同,有一个优势--可以有序取单个对象,但也有一个劣势,就是删除单个对象需要遍历该集合,由于我的应用不大可能用到单个删除,所以我暂时还没有想到一种数据结构可以实现不遍历的单个对象删除,又能满足现有的API都高效完成,如果谁有更好的代码来实现请回复

目前想到可以实现的方法:

add(o);
addAll(array)
contain(o);
get(int);
getAll();
sort(comparator); //传进去的是一个fn,还没有写例子....
size();
remove();
reverse();


基本数据结构是两个数组,一个是index数组,数组下标连续,用来存放第二个数组的下标,另一个是存放对象的数组,不连续,下标是对象的id或者对象中其他任何可以转换成唯一Integer的Field(Set也要求放进去的对象必须要有hashCode嘛,不然没法区别第一个和第二个)

实现的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();
}
目前还有一个addAll方法也是暂时没有想到有什么不用遍历的好的实现

前同事提供了一种完全和Set一样的实现,效率满高
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();
}

还有一个朋友的实现和我最初的差不多,但是remove方法相当有创意,用正则表达式来删除
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)
}

有人回复说需要添加做验证,我觉得不必了,如果添加的值和之前的一样就直接替换好了,如果希望不被replace,直接在添加新对象之前用contain判断一次就可以了,毕竟在我的实现中已不是完全在模拟Set了,目前更倾向于设计一个更高效和强大的集合类


评论

# re: 用Javascript模拟Java的Set  回复  更多评论   

2007-10-12 12:42 by 千里冰封
有意思,用javascript

# re: 用Javascript模拟Java的Set  回复  更多评论   

2007-10-13 11:29 by 风姿物语
添加不带验证的吗?

我觉得可以完全将Array的 一些方法重载以替换默认的实现,例如“排序”:
function t(id, name)
{
this.id = id;
this.name = name;
}

var temp = new Array();

temp[0] = new t(1, "ghost");
temp[1] = new t(7, "feishao");
temp[2] = new t(4, "yahoo");
temp[3] = new t(3, "china");

temp.sort(function(x, y) {
if (x.id <= y.id)
return -1;
else
return 1;
}
);
for (var i = 0; i < temp.length; i++)
{
if (temp[i] != null)
document.write(temp[i].id + "-----" + temp[i].name + "
");
}
至于“删除”功能还没有想到好的方法,估计还是得遍历。

只有注册用户登录后才能发表评论。


网站导航: