我遇到了以下问题。
我想要一个包含1到100,000,000所有数字的哈希集合。
我尝试了以下代码:
var mySet = new HashSet<int>();
for (var k = 1; k <= 100000000; k++)
mySet.Add(k);
由于某个地方出现了内存溢出的问题,在大约4,900万次操作时,那段代码未能成功执行。而且,该方法速度较慢,且内存使用过多。
后来我尝试了这个方法。
var mySet = Enumerable.Range(1, 100000000).ToHashSet();
其中ToHashSet()代码如下:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
return new HashSet<T>(source);
}
我又遇到了内存溢出的问题,但是与先前的代码相比,我能够输入更多的数字。
以下内容是有效的:
var tempList = new List<int>();
for (var k = 1; k <= 100000000; k++)
tempList.Add(k);
var numbers = tempList.ToHashSet();
在我的系统中,仅用Enumerable.Range()需要4个时钟周期,而填充tempList需要约800毫秒!我确实需要HashSet,否则查找值需要太长时间(我需要它是O(1)),如果可以以最快的方式完成就太好了。现在我的问题是:为什么前两种方法会导致内存溢出而第三种方法不会?HashSet在初始化时是否对内存进行了特殊处理?我的系统有16GB内存,所以当我遇到溢出异常时感到非常惊讶。
Enumerable.Range
之所以如此快,是因为在运行时它实际上并不生成任何内容。只有当它被使用(例如在ToHashSet
调用中)时,它才会开始生成数字。 - Chris