JavaScript中是否有类似Java集的数据结构?

JavaScript中是否有类似Java集的数据结构?,java,javascript,dojo,set,Java,Javascript,Dojo,Set,我想在JavaScript中使用一个数据结构,可以用来存储ID的数量。我应该能够检查该集合中是否已经存在一个键,比如Java集合 我希望实现如下相同的行为(此代码是Java的): Set st=new HashSet(); //添加元素 如果(st.contains(“aks”)){ //做点什么 } 我想要一个与上述代码等价的JavaScript/dojo。可能有一个关联数组/哈希表/字典(我不知道它到底是如何调用的),使用set元素作为键,“其他任何东西”作为值 insert: mySet

我想在JavaScript中使用一个数据结构,可以用来存储ID的数量。我应该能够检查该集合中是否已经存在一个键,比如Java集合

我希望实现如下相同的行为(此代码是Java的):

Set st=new HashSet();
//添加元素
如果(st.contains(“aks”)){
//做点什么
}

我想要一个与上述代码等价的JavaScript/dojo。

可能有一个关联数组/哈希表/字典(我不知道它到底是如何调用的),使用set元素作为键,“其他任何东西”作为值

insert: mySet[key] = "Whatever";

delete: mySet[key] = null;

check: if (mySet[key] != null) { ... }

为什么不使用普通对象并检查JavaScript的
hasOwnProperty
是否存在键

var x = {};
x['key'] = 'val';
x.hasOwnProperty('key'); // true //
x.hasOwnProperty('key2'); // false //
下面是一个更高级的用例:

var x = {};
var prefix = 'item_';
for(var i=0;i<10;i++){
   x[prefix+i] = 'value '+(i+1);
}
x.hasOwnProperty('item_6'); // true //
x.hasOwnProperty('other key'); // false //

Hash是实现Set的很好的候选者。您可以使用如下函数创建一个集合:

function set () {
    var result = {};
    for (var i = 0; i < arguments.length; i++) result[arguments[i]] = true;
    return result;
}

集合没有键。它们只有一组值,但映射有成对的键/值实体

因此,您有两种选择。每种方法都有其缺点和优点:

  • 您可以使用如上所述的JavaScript对象。实际上,它是一个映射/关联数组/哈希表。它的一个优点是——你可以用这种结构保证钥匙是独一无二的物品。它的缺点与这个问题有关——你必须保留一些你根本不需要的额外信息。地图的价值。trues或其他一些值。没关系。你为什么需要它们

  • <> >为了解决前面的缺点,您可以考虑使用JavaScript数组。但是,您必须编写一些包装器,使数组的行为看起来像集合的行为。此外,通过uniqueId进行搜索的操作将比针对哈希表的相同操作慢,因为您必须通过数组的所有项进行迭代

    因此,我认为您应该更喜欢哈希表而不是数组,您可以在其他文章中找到这些示例。但也许你应该考虑改变你的数据结构。如果可能的话,不要将uniqueId保留为具有未加密值的键。让您的唯一ID指向使用这些唯一ID的一些真实对象


    附言:还有一件事。数组实际上也是对象。因此,它们也可以用作哈希表/映射

    我已经编写了一个JavaScript哈希集实现,它可以满足您的需要,并允许任何对象成为该集的成员:

    但是,如果只需要存储字符串,则可以通过将集合成员存储为普通对象的属性名来完成更简单的操作。例如:

    function StringSet() {
        var setObj = {}, val = {};
    
        this.add = function(str) {
            setObj[str] = val;
        };
    
        this.contains = function(str) {
            return setObj[str] === val;
        };
    
        this.remove = function(str) {
            delete setObj[str];
        };
    
        this.values = function() {
            var values = [];
            for (var i in setObj) {
                if (setObj[i] === val) {
                    values.push(i);
                }
            }
            return values;
        };
    }
    
    关于实现的注意事项:
    val
    StringSet
    实现内部使用的对象,每个集都是唯一的。将属性名称构成集合(
    setObj
    )的对象的属性值与
    val
    进行比较,无需进行
    hasOwnProperty()
    检查,并确保只有添加到集合中的字符串才会显示在
    值中

    用法示例:

    var set = new StringSet();
    set.add("foo");
    set.add("bar");
    
    alert(set.contains("foo")); // true
    alert(set.contains("baz")); // false
    
    set.values(); // ["foo", "bar"], though not necessarily in that order
    set.remove("foo");
    set.values(); // ["bar"]
    

    不需要Dojo,这是Javascript固有的。使用对象。听起来您只需要键,而不需要值。查找是固定时间

    var st = {'aks':1, 'foo':1, 'bar':1};  // or could start with empty {}. 1 could be any value of any type, it's just short.
    
    //add elements
    st.baz = 1;
    
    //or load up dynamically
    
    myArrayOfStrings.forEach(function(key){
     st[key] = 1;
    });
    
    
    if("aks" in st){
      //do something
    }
    

    感谢您的回复。但我如何检查它是否包含键?我想在javascriptSee last edit中获得它。请参阅上次编辑,试图澄清。@G B它被称为对象。这是JavaScript的基本数据类型。@G B实际上,在
    检查
    的情况下,正确的方法是比较
    未定义的
    如果(mySet[key]!==未定义的){…}
    。在JavaScript中,一个项目仍然可以存在,并且其值为
    null
    。更正:正确检查的唯一方法是使用
    hasOwnProperty
    。感谢您的回复:我想先向对象动态添加多个键,然后再检查对象中是否存在键。怎么做?@键可以是任何字符串(甚至是包含字符串的变量)。我将用一个例子进行更新。@gbwith
    delete x['key']。同样,钥匙可以是任何东西。我使用文字只是为了方便。不一定是:
    Object.prototype.foo=“true”;警报(x[“foo”]==true)
    如果您正在创建一个简单的对象,并且原型不是问题,只需使用“in”操作符即可。它读起来好多了。像x[“foo”]这样的静态查找可以写为x.foo。
    forEach
    在IE中不受支持。这还需要一个
    hasOwnProperty()
    检查,以防其他代码执行了类似
    Object.prototype.aks=1
    的操作。是的,在我的示例中,我假设ES5没有人修改对象原型,这是最佳实践。避免调用hasOwnProperty()的目的是什么?平等性检查是否更快?如果是这样,你怎么知道?@JørgenFogh:我怀疑等式检查可能更快,因为它避免了函数调用的开销。我还没有测试过这个,所以请随意创建一个基准;我很想看看结果。@JørgenFogh:对象比较的另一个优点是它不会出错。
    function StringSet() {
        var setObj = {}, val = {};
    
        this.add = function(str) {
            setObj[str] = val;
        };
    
        this.contains = function(str) {
            return setObj[str] === val;
        };
    
        this.remove = function(str) {
            delete setObj[str];
        };
    
        this.values = function() {
            var values = [];
            for (var i in setObj) {
                if (setObj[i] === val) {
                    values.push(i);
                }
            }
            return values;
        };
    }
    
    var set = new StringSet();
    set.add("foo");
    set.add("bar");
    
    alert(set.contains("foo")); // true
    alert(set.contains("baz")); // false
    
    set.values(); // ["foo", "bar"], though not necessarily in that order
    set.remove("foo");
    set.values(); // ["bar"]
    
    var st = {'aks':1, 'foo':1, 'bar':1};  // or could start with empty {}. 1 could be any value of any type, it's just short.
    
    //add elements
    st.baz = 1;
    
    //or load up dynamically
    
    myArrayOfStrings.forEach(function(key){
     st[key] = 1;
    });
    
    
    if("aks" in st){
      //do something
    }