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 閱讀(3548) 評論(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 + "
          ");
          }
          至于“刪除”功能還沒有想到好的方法,估計還是得遍歷。

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 棋牌| 栾川县| 腾冲县| 赞皇县| 宜章县| 玉树县| 邻水| 田林县| 凯里市| 清镇市| 博兴县| 利津县| 司法| 昭通市| 广东省| 鞍山市| 托克逊县| 阳东县| 巩留县| 金湖县| 修文县| 兴海县| 延吉市| 尖扎县| 垣曲县| 芜湖市| 乡城县| 伊宁市| 彭阳县| 屏东市| 德令哈市| 额尔古纳市| 新野县| 汝城县| 南丰县| 锡林郭勒盟| 鹤岗市| 准格尔旗| 大港区| 松潘县| 阳信县|