关于c#:. NET数据结构:ArrayList,List,HashTable,Dictionary,SortedList,SortedDictionary – 速度,内存以及何时使用?

.NET data structures: ArrayList, List, HashTable, Dictionary, SortedList, SortedDictionary — Speed, memory, and when to use each?

.NET有许多复杂的数据结构。不幸的是,它们中的一些非常相似,我不总是确定什么时候使用一个,什么时候使用另一个。我的大多数C和VisualBasic书籍都在一定程度上讨论过它们,但它们从未真正深入到任何实际细节中。

array、array list、list、hashtable、dictionary、sortedlist和sorteddictionary有什么区别?

哪些是可枚举的(ilist——可以执行"foreach"循环)?哪些使用键/值对(IDICT)?

内存占用怎么办?插入速度?检索速度?

还有其他值得一提的数据结构吗?

我仍在寻找关于内存使用和速度(big-o符号)的更多细节。


从我的头顶上:

  • Array表示一个老式的内存数组,类似于普通type[]数组的别名。可以枚举。不能自动增长。我假设插入和检索速度非常快。

  • ArrayList—自动增长阵列。增加了更多的开销。可以枚举.,可能比普通数组慢,但仍然很快。这些在.NET中经常使用

  • List——我的一个fav——可以与泛型一起使用,所以您可以有一个强类型数组,例如List。除此之外,它的行为与ArrayList非常相似。

  • Hashtable—普通的旧哈希表。o(1)至o(n)最坏情况。可以枚举值和键属性,并执行键/值对

  • Dictionary—与上面相同,仅通过泛型强类型,如Dictionary

  • SortedList—已排序的通用列表。在插入时放慢速度,因为它必须找出放置东西的位置。可以枚举,可能在检索时相同,因为它不必诉诸于此,但删除将比普通的旧列表慢。

我经常使用ListDictionary——一旦开始使用强类型的泛型,就很难回到标准的非泛型类型。

还有很多其他的数据结构-有KeyValuePair,你可以用它来做一些有趣的事情,还有一个SortedDictionary,它也很有用。


如果可能的话,使用仿制药。这包括:

  • 列表而不是数组列表
  • 字典而不是哈希表


首先,.NET中的所有集合实现IEnumerable。

其次,许多集合是重复的,因为在框架的2.0版本中添加了泛型。

因此,尽管通用集合可能会添加特性,但在大多数情况下:

  • list是arraylist的通用实现。
  • 字典是哈希表的通用实现

数组是一个固定大小的集合,可以更改存储在给定索引中的值。

SortedDictionary是基于键排序的IDictionary。SortedList是基于所需IComparer排序的IDictionary。

因此,IDictionary实现(那些支持键值对的实现)是:*哈希表*词典*排序列表*排序限制

在.NET 3.5中添加的另一个集合是哈希集。它是一个支持集合操作的集合。

另外,LinkedList是一个标准的链表实现(链表是一个用于更快检索的数组列表)。


一个很好的备忘表,提到了数据结构、算法等的复杂性。


以下是一些一般性的提示:

  • 您可以在实现IEnumerable的类型上使用foreachIList本质上是一个IEnumberable,具有CountItem属性(使用零基索引访问项目)。另一方面,IDictionary意味着您可以通过任何哈希索引访问项目。

  • ArrayArrayListList都执行IListDictionarySortedDictionaryHashtable实施IDictionary

  • 如果您使用的是.NET 2.0或更高版本,建议您使用上述类型的通用副本。

  • 对于这些类型上各种操作的时间和空间复杂性,您应该参考它们的文档。

  • .NET数据结构位于System.Collections命名空间中。有些类型库(如PowerCollections)提供附加的数据结构。

  • 要彻底了解数据结构,请参考CLR等资源。


.NET数据结构:更多关于为什么ArrayList和List实际上不同的讨论数组

正如一个用户所说,数组是"老派"集合(是的,数组被视为集合,但不是System.Collections的一部分)。但是,与其他收藏相比,数组的"老派"是什么,即你在标题中列出的那些(这里是arraylist和list(of t))?让我们从基本知识开始,看看数组。好的。

首先,Microsoft.NET中的数组是"允许将多个[逻辑相关的]项视为单个集合的机制"(请参阅链接文章)。那是什么意思?数组按顺序存储单个成员(元素),一个接一个地存储在具有起始地址的内存中。通过使用数组,我们可以轻松地访问从该地址开始的顺序存储元素。好的。

除此之外,与编程101常见概念相反,数组实际上可能非常复杂:好的。

数组可以是一维的、多维的,也可以是Jadded(锯齿状的数组值得一读)。数组本身不是动态的:一旦初始化,n大小的数组就保留足够的空间来容纳n个对象。数组中的元素数不能增长或收缩。Dim _array As Int32() = New Int32(100)在内存块上保留足够的空间,以便数组包含100到32个基元类型对象(在这种情况下,数组初始化为包含0)。此块的地址返回到_array。好的。

根据本文,公共语言规范(CLS)要求所有数组都是基于零的。.NET中的数组支持非基于零的数组;但是,这并不常见。由于零基数组的"通用性",微软花费了大量时间优化它们的性能;因此,单维零基(szs)数组是"特殊"的,实际上是数组的最佳实现(而不是多维的等),因为szs对manipula有特定的中间语言指令。给他们打电话。好的。

数组总是通过引用(作为内存地址)传递的,这是需要知道的数组难题中的一个重要部分。当它们执行边界检查(将引发错误)时,也可以在数组上禁用边界检查。好的。

同样,对数组最大的阻碍是它们不可重定大小。它们具有"固定"容量。将ArrayList和List(of T)引入我们的历史:好的。arraylist-非泛型列表

arraylist(连同List(Of T)--虽然这里有一些关键的区别,稍后解释),也许最好被认为是收藏的下一个添加(广义上)。arraylist继承自ilist(ICollection)接口的后代。数组列表本身比列表更庞大——需要更多的开销。好的。

IList确实使实现能够将arraylist视为固定大小的列表(类似于数组);但是,除了arraylist添加的附加功能之外,在这种情况下,使用固定大小的arraylist作为arraylist(优于数组)并没有真正的优势,因为它的速度明显较慢。好的。

在我看来,数组列表不能交错:"使用多维数组作为元素…不支持""。再一次,又一颗钉子钉进了阵列列表的棺材。arraylist也不是"类型化的"—也就是说,在所有内容的下面,arraylist只是一个对象的动态数组:Object[]。这在实现数组列表时需要大量装箱(隐式)和取消装箱(显式),这又增加了它们的开销。好的。

未经证实的想法:我想我记得我读过或听过我的一位教授说过,数组列表是试图从数组转移到列表类型集合的一种混蛋概念子,也就是说,虽然数组曾经是一个很大的改进,但随着进一步的发展,它们不再是最佳选择。关于托收好的。(T的)列表:arraylist变成了什么(并且希望变成什么)

内存使用的差异非常显著,以至于一个列表(Int32)消耗的内存比一个包含相同基元类型的数组列表少56%(在上面的绅士链接演示中为8 MB对19 MB:同样,链接在这里),尽管这是64位机器的复合结果。这种差异实际上证明了两件事:第一(1),装箱的int32类型"object"(arraylist)比纯的int32基元类型(list)大得多;第二(2),由于64位机器的内部工作,这种差异是指数级的。好的。

那么,有什么区别,什么是t的列表?msdn将List(Of T)定义为"…可由索引访问的对象的强类型列表。"这里的重要性是"强类型"位:一个列表(t)"识别"类型并将对象存储为其类型。因此,Int32存储为Int32类型,而不是Object类型。这消除了装箱和拆箱引起的问题。好的。

msdn指定此差异仅在存储基元类型而不是引用类型时起作用。同样,这种差异也在很大程度上发生:超过500个元素。更有趣的是,msdn文档中写道:"使用list(of t)类的特定类型实现而不是使用arraylist类是对您有利的……"好的。

本质上,t的list是arraylist,但更好。它是arraylist的"一般等价物"。像arraylist一样,在排序之前不能保证它是被排序的(如图所示)。list(of t)还有一些附加功能。好的。好啊。


我对这个问题表示同情-我也发现了。这个选择令人困惑,所以我科学地着手研究哪种数据结构最快(我用vb进行了测试,但我认为c是相同的,因为两种语言在clr级别都做相同的事情)。您可以在这里看到我进行的一些基准测试结果(还讨论了在哪些情况下最适合使用哪种数据类型)。


泛型集合将比它们的非泛型集合执行得更好,尤其是在迭代许多项时。这是因为拳击和拆箱不再发生。


哈希表/字典是O(1)性能,这意味着性能不是大小的函数。这很重要。

编辑:实际上,哈希表/字典<>查找的平均时间复杂度是O(1)。


它们的拼写很清楚。只需键入System.Collections。或者system.collections.generics(首选),您将得到可用内容的列表和简短描述。


高频系统交易工程哈希表与字典的重要说明:线程安全问题

哈希表是线程安全的,可供多个线程使用。字典公共静态成员是线程安全的,但不保证任何实例成员是线程安全的。

因此在这方面,hashtable仍然是"标准"选项。


最流行的C数据结构和集合

  • 数组
  • 阵列列表
  • 链表
  • 词典
  • 哈希集
  • 排队
  • 有序列表

C.NET有很多不同的数据结构,例如,最常见的是数组。然而,C有许多更基本的数据结构。选择要使用的正确数据结构是编写结构良好且高效的程序的一部分。

在本文中,我将介绍内置的C数据结构,包括C.NET 3.5中引入的新结构。注意,这些数据结构中的许多适用于其他编程语言。

数组

可能最简单和最常见的数据结构是数组。C数组基本上是一个对象列表。它的定义特征是所有对象都是相同的类型(在大多数情况下),并且有特定数量的对象。数组的性质允许根据元素在列表中的位置(也称为索引)快速访问元素。C数组的定义如下:

1
[object type][] myArray = new [object type][number of elements]

一些例子:

1
2
 int[] myIntArray = new int[5];
 int[] myIntArray2 = { 0, 1, 2, 3, 4 };

从上面的示例中可以看到,可以不使用元素或从一组现有值初始化数组。在数组中插入值只要合适就很简单。当元素多于数组的大小时,操作会变得昂贵,此时需要扩展数组。这需要更长的时间,因为必须将所有现有元素复制到新的更大的数组中。

阵列列表

C数据结构arraylist是一个动态数组。这意味着数组列表可以有任意数量的对象和任何类型的对象。此数据结构旨在简化向数组中添加新元素的过程。在引擎盖下,arraylist是一个数组,它的大小在每次耗尽空间时都翻倍。将内部数组的大小翻一番是一种非常有效的策略,从长远来看可以减少元素复制的数量。我们不能在这里证明这一点。数据结构非常易于使用:

1
2
3
4
    ArrayList myArrayList = new ArrayList();
    myArrayList.Add(56);
    myArrayList.Add("String");
    myArrayList.Add(new Form());

arraylist数据结构的缺点是必须将检索到的值强制转换回其原始类型:

1
int arrayListValue = (int)myArrayList[0]

您可以在此处找到的来源和更多信息:

  • C数据结构
  • 收集和数据结构
  • 列表与IEnumerable、IQueryable、ICollection和IDictionary
  • System.Collections.Generic命名空间
  • System.Collections命名空间

一般集合和非一般集合之间存在细微的差别,而不是细微的差别。它们只使用不同的底层数据结构。例如,hashtable保证一个编写器和多个读卡器不同步。字典没有。


实际上,我认为msdn有助于为所有这些问题提供很好的答案。只需查找.NET集合。