From:
Http://www.blogjava.net/hunteva/archive/2007/10/12/152282.html
Recently, many Ajax applications have encountered many places that require a rich set of JavaScript. Unfortunately, JavaScript is not as powerful collection classes as Java collections, so I plan to write a set simulation API by myself, the simulation class written in the result is a little different from the set class. It has an advantage that a single object can be obtained in sequence, but it also has a disadvantage that deleting a single object requires traversing the set, because my application is unlikely to use a single Delete, I have not yet thought of a data structure that can delete a single object without traversing, and can meet the needs of existing APIs efficiently, if anyone has better code for implementation, please reply.
The following methods can be implemented:
Add (O );
Addall (array)
Contain (O );
Get (INT );
Getall ();
Sort (comparator); // The input is a FN, and no examples have been written ....
Size ();
Remove ();
Reverse ();
The basic data structure is two arrays, one is the index array, the array subscript is continuous, used to store the subscript of the second array, the other is to store the array of objects, not continuous, subscript is the Object ID or any other field in the object that can be converted to a unique integer (Set also requires that the object to be put must have hashcode, otherwise there is no way to distinguish the first and second)
Implemented 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 ();
}
At present, there is another addall method, which is also a good implementation that does not need to be traversed.
Previous colleagues provided a completely same implementation as set, with High Efficiency
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 ();
}
Another friend's implementation is similar to my original one, but the remove method is quite creative and can be deleted using regular expressions.
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)
}
Some people reply that they need to add for verification. I don't think it is necessary. If the added value is the same as the previous one, it will be replaced directly. If you want to not be replaced, you can use contain to judge a new object directly before adding it. After all, in my implementation, the set is not completely simulated. At present, I prefer to design a more efficient and powerful collection class.