HashSet<T>
表示值的集合。这个集合的元素是无须列表,同时元素不能重复。由于这个集合基于散列值,不能通过数组下标访问。
List<T>
表示可通过索引访问的对象的强类型列表。内部是用数组保存数据,不是链表。元素可重复,是有序列表,根据调用add的时间先后进行排序。每次添加删除操作会重新排序。例如有100个元素,删除掉下标99的元素后,无法再通过下标99访问数据。
性能分析
HashSet对数据的检索效率(contains函数)比List 快。HashSet存储数据时将数据通过散列函数直接映射到地址,所有取值时可以直接取到,时间复杂度为O(1)。List检索时需要一个个的进行值比较,最多需要比较到数组末尾,时间复杂度为O(n),n为元素个数。
实例分析
public static void Test()
{
int dataCount = 10; //数据个数
int loopCount = 10000000; //循环次数
Stopwatch sw = new Stopwatch();
HashSet<int> hash = new HashSet<int>();
List<int> list = new List<int>();
list.AddRange(Enumerable.Range(0, dataCount));
//list.Select(x => hash.Add(x));
for (int i = 0; i < dataCount; i++)
{
hash.Add(i);
}
sw.Restart();
for (int i = 0; i < loopCount; i++)
{
hash.Contains(999999);
}
sw.Stop();
Console.WriteLine("HASH:" + sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < loopCount; i++)
{
list.Contains(999999);
}
sw.Stop();
Console.WriteLine("LIST:" + sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < loopCount; i++)
{
hash.Add(999999999);
hash.Remove(999999999);
}
sw.Stop();
Console.WriteLine("HASH:" + sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < loopCount; i++)
{
list.Add(99999909);
list.Remove(99999909);
}
sw.Stop();
Console.WriteLine("LIST:" + sw.ElapsedMilliseconds);
}
当数据量较小时,list的增加删除性能有优势,当数据量较大,则hashset的性能有巨大优势
数据量10
数据量50
数据量1000
数据量10000