Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 快速检查是否存在,然后插入分类列表_C#_Performance_Sortedlist - Fatal编程技术网

C# 快速检查是否存在,然后插入分类列表

C# 快速检查是否存在,然后插入分类列表,c#,performance,sortedlist,C#,Performance,Sortedlist,每当我想插入到SortedList中时,我会检查项目是否存在,然后插入。这是否执行了两次相同的搜索?一次查看项目是否存在,然后再次查找插入项目的位置?有没有一种方法可以优化它来加速它,或者这只是一种方法,不需要更改 if( sortedList.ContainsKey( foo ) == false ){ sortedList.Add( foo, 0 ); } 您可以将项目添加到哈希集和列表中,在哈希集中搜索是查看是否必须向列表中添加值的最快方法 if( hashSet.Contain

每当我想插入到
SortedList
中时,我会检查项目是否存在,然后插入。这是否执行了两次相同的搜索?一次查看项目是否存在,然后再次查找插入项目的位置?有没有一种方法可以优化它来加速它,或者这只是一种方法,不需要更改

if( sortedList.ContainsKey( foo ) == false ){
    sortedList.Add( foo, 0 );
}

您可以将项目添加到哈希集和列表中,在哈希集中搜索是查看是否必须向列表中添加值的最快方法

if( hashSet.Contains( foo ) == false ){
    sortedList.Add( foo, 0 );  
    hashSet.Add(foo);
}

ContainsKey
执行二进制搜索,即O(logn),因此除非您的列表很大,否则我不会太担心它。而且,大概在插入时,它会执行另一个二进制搜索来查找要插入的位置


避免这种情况的一种方法(搜索两次)是使用列表方法。如果找不到该项,则返回负值,该负值是该项插入位置的按位补码。因此,您可以查找一个项目,如果它不在列表中,您就可以确切地知道应该将其插入到哪里以保持列表的排序

您可以使用索引器。索引器在内部以最佳方式执行此操作,首先使用二进制搜索查找与键对应的索引,然后使用此索引替换现有项。否则,将通过考虑已计算的索引来添加新项

list["foo"] = value;
无论密钥是否已存在,都不会引发异常


更新

如果新值与旧值相同,则替换旧值的效果与不执行任何操作的效果相同

请记住,二进制搜索已经完成。这意味着在1000个项目中找到一个项目需要大约10个步骤<代码>日志2(1000)~=10。因此,进行额外的搜索不会对速度产生重大影响。在1000000个项目中搜索只会使该值加倍(~20步)


但在任何情况下,通过索引器设置值只会执行一次搜索。我使用Reflector查看了代码,可以证实这一点。

如果这不能回答您的问题,我很抱歉,但我必须说,.NET中的默认集合结构有时在功能上受到不合理的限制。如果
Add
方法返回一个表示成功/失败的布尔值,则可以处理这个问题,就像
HashSet.Add
一样。所以一切都是一步到位的。事实上,整个
ICollection.Add
应该是一个布尔值,以便在实现方面强制执行,就像Java中的
Collection
一样

您可以使用中指出的
SortedDictionary
结构,也可以使用中的
HashSet
SortedList
的组合,以获得更好的性能,但这两种结构都不是真正坚持只做一次。我尝试了几个开源项目,看看在这方面是否有更好的实现,但没有找到

您的选择:

  • 在绝大多数情况下,做两次查找是可以的,不会造成太大的伤害。坚持一个。没有内置的解决方案

  • 编写自己的
    SortedList
    类。一点也不难

  • 如果你绝望了,你可以使用反射。
    Insert
    方法是SortedList类中的私有成员。请不要这样做。这是一个非常糟糕的选择。这里提到的是完整性

  • SortedList
    是一种缓慢的数据结构,您可能根本不应该使用它。您可能已经考虑过使用
    SortedDictionary
    ,但觉得不方便,因为这些项没有索引(您无法编写
    SortedDictionary[0]
    ),并且您可以为
    SortedList
    编写操作,但不能编写
    SortedDictionary

    但是,如果您愿意切换到第三方库,则可以通过更改到不同的数据结构来获得更好的性能

    Loyc核心库包含的数据类型与SortedList的工作方式相同,但在列表较大时速度会显著加快。它叫


    现在,回答您最初的问题:是的,按照您编写代码的方式,它执行两次搜索和一次插入(插入是最慢的部分)。如果切换到
    BDictionary
    ,有一种方法可以将这两个操作组合成一个操作。如果添加了指定项,则返回true;如果指定项已存在,则返回false。

    是否存在
    else
    分支?如果你展示它,你可能会得到一个更好的答案。
    SortedList
    不是一个特别好的数据结构;这很少令人满意。为什么不使用
    SortedDictionary
    或仅仅使用
    列表
    ?很有可能两个中的一个会更好。Dasblinkenlight-我没有其他礼物。如果钥匙已经存在,我什么也不做。cirrus-我不认为ContainsKey很慢,我想知道ContainsKey与Add-together组合是否必要。提示:如果(!sortedList.ContainsKey(foo))@Servy,我不同意。当用户想要的只是缺少适当数据结构的特性时,最好使用不缺少的结构。不幸的是,在“考虑到情况”的情况下,这才是合适的时机。我重复一遍,我只是反对你笼统的说法,即“考虑到目前的情况,
    SortedList
    是一个糟糕的结构”。所以这里有一个问题:如果我需要大量基于索引的操作、二进制搜索和排序地图上的最小/最大操作,该怎么办?这并不罕见。鉴于.NET中的选项,没有比SortedList更好的选择了。SortedDictionary在这里是一个糟糕的选择。更好的是,使用哈希集,您甚至不需要检查它是否存在,您只需再次添加它,如果它已经存在,则不会发生任何事情(性能影响非常低)。唯一的缺点是你没有得到排序。为什么还要保留
    sortedli呢