我的大多数编程经验都是使用一种语言,其中有一个集合数据结构 - 一个数组。现在我主要在.NET工作,我开始欣赏可用的大量工具,但我也发现很难确定哪种工具最适合每个问题。我发现这通常是收藏品的情况。
我确信我能够根据时间/经验更快地找到合适的工具,但是有人可以提供一些关于哪些收集类适合哪些工作的指导?有任何好的经验法则可以遵循吗?
编辑:我发现我几乎总是使用List(T),这就是提出这个问题的原因。我知道使用其他类有非常具体的原因。尽管List(T)工作时间最多,但我希望避免在其他结构更适合时将某些东西堵塞到通用列表中。我必须能够发现这些案件。
谢谢!
答案 0 :(得分:15)
你没有说过你以前用过的语言,但我觉得如果你认为阵列是唯一可用的,那么你可能会错了。
例如,C ++本身仅支持数组“集合”(这里非常松散地使用“集合”),但是通过添加指针,您可以为.Net中可用的任何集合数据结构实现等效。实际上,如果你查看C ++标准模板库,你会发现大多数常见结构的库存实现。附加结构的原因是数组并不总是,或者甚至经常是用于数据集合的最合适的结构。它有许多限制,可以通过一个或另一个集合来解决,使用这些不同的集合,您通常可以从更少的代码中获得更高的性能,并减少您的数据结构实施中也存在错误的可能性。
在决定使用哪种集合类型时,您需要查看它将如何使用大多数。例如,集合中的所有对象是否应该是相同类型,继承自相同类型或任何类型?您是否经常添加和删除项目?如果是这样,您是否总是推送/弹出,排队/出列项目或是否需要将项目添加到特定位置?您会按键,索引还是两者查找特定项目?如果按键,键是如何确定的?
一些更常见的集合:
List<T>
应该用于大多数的习惯使用数组的情况。它支持使用与数组相同的语法查找索引,其性能接近于数组,是强类型的,并使非常易于添加或删除项目,并且非常快速地追加或弹出项目(插入特定位置要慢得多)。
LinkedList<T>
应该听起来很熟悉。它使用类似于List的语法,但进行了不同的优化:查找速度较慢,因为它们需要遍历列表,而将项目添加或删除到特定位置的速度要快得多。
Dictionary<TKey, TValue>
使用类似于List<T>
的语法,但您不是使用数组索引,而是将键值放在括号中。字典很棒,因为按密钥查找特定项目被认为是非常快,因为无论字典中有多少项目,它总是花费大约相同的时间来找到你的需要。
SortedList<TKey, TValue>
的工作原理与字典类似,但有一点例外,当您迭代它时,按键排序的项目将返回。但是,如果没有先迭代它之前的所有项目,则无法查找第n个项目。
KeyedCollection
经常被忽略,因为它隐藏在与其他一些集合不同的命名空间中,你必须实现一个(非常简单的)函数来使用它。它也像字典一样工作,另外它支持通过索引轻松查找。当项目的关键字是项目本身的简单属性时,通常使用它。
不要忘记旧的备用证:Stack
和Queue
。同样,如果你有任何正式的计算机科学教育,你应该已经很清楚这些工作是如何根据他们的名字进行的。
最后,大多数这些集合(包括数组!)实现了一组通用接口。这些接口非常有用,因为您可以针对接口而不是特定集合编写程序,然后您的函数可以接受实现该接口的任何集合。例如,无论您是传入字符串数组,List<string>
还是其他任何IEnumerable<string>
,以下代码都将有效:
void WriteToConsole(IEnumerable<string> items)
{
foreach (string item in items)
{
Console.WriteLine(item);
}
}
值得关注的其他界面包括IList<T>
,ICollection<T>
和IQueryable<T>
。
答案 1 :(得分:3)
通用列表(列表)适合常用。他们不执行装箱和拆箱。所以没有表现出来的问题。
List<string> items = new List<string>();
items.Add("abc");
items.Add("dfg");
ArrayLists 接受任何对象作为项目。所以它们适合存储多种类型的情况。例如,如果你需要在同一个集合中存储一个int和一个字符串,那么arraylist对此很有用。
ArrayList items = new ArrayList();
items.Add("abc");
items.Add(1);
items.Add(DateTime.Now);
SortedLists 和 Hashtables 是商店键值对。您可以为商品定义一个键。这有助于您快速找到它们。 SortedLists自动排序Hastables。
Hashtable items1 = new Hashtable();
items1.Add("item1", "abc");
items1.Add("item2", "dfg");
SortedList items2 = new SortedList();
items2.Add("Second", "dfg");
items2.Add("First", "abc");
希望这有帮助!
答案 2 :(得分:1)
与计算机科学中的许多其他事物一样,当有多种选择时,通常意味着有多种方法可以做某事。正如其他人所说,每个系列都有各种优缺点。无论您是否使用集合的通用版本,最终所有集合都提供以下操作:
不同的集合对于每个操作都具有不同的性能特征。例如,数组可以快速更新项目,但插入或删除项目需要更长的时间。查找非常快。
将其与List进行比较。列表插入速度非常快。查找需要更长时间。更新和删除操作要求您已经拥有该项目并且非常快。数组和List的枚举大致相同。
所有集合也有某些行为,例如,集合是否保持排序。如果是这样,那么插入/更新/删除操作将花费更长时间,但会加快查找速度。
因此,根据您的程序正在执行的操作,大多数情况下将确定要使用的集合。
答案 3 :(得分:0)
Stacks,Queues,SortedList,Dictionary,HashTable等集合都是标准数据结构,在各种情况下派上用场。
队列启用FIFO实现,无需您自己完成。堆栈给你LIFO。 SortedLists为您提供预先排序的列表,依此类推。
集合名称空间中还有许多其他内容,并且都讨论了here。
答案 4 :(得分:0)
我可以提供的两个提示: 1.尽可能使用通用集合。 2.在HashSet和List泛型集合之间进行决策时,请真正了解您将使用它们的内容。 Hashsets在搜索时可能会更快,但插入速度也会变慢(我已找到)。
答案 5 :(得分:0)
算法和数据结构。每一个都有其优点和缺点,每一个都有其目的。
答案 6 :(得分:0)
有很多与此问题相关的帖子,您必须考虑您真正需要做什么。你需要一个基于字符串的密钥(¿)如何填充数据,你需要一个本地方法来查找是否存在任何密钥,或者是否存在任何值(?)
泛型是我最常用的,但其他人有理由;)
http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=5119