具有初始容量的Powershell哈希表

时间:2018-11-15 15:38:57

标签: powershell hashtable

我想知道您如何在Powershell中以初始容量声明哈希表。我知道我希望它有多大,但是我必须在循环中为其分配值。

类似这样:

$hashtable = @{} (100)

1 个答案:

答案 0 :(得分:2)

JeroenMostert很好地说明了为什么您不需要指定初始容量的原因:

  

请注意,尽管预先指定容量通常不会在内存或运行时方面为您带来多大好处;它已经实现了大幅度的动态调整大小,并且如果您的猜测不成立,那么好处基本上就会消失。

如果确实需要指定初始容量

PetSerAl求助。

由于PowerShell的哈希表对于键查找总是不区分大小写,因此[hashtable]::new(100)不能 起作用,因为默认情况下是创建案例-敏感哈希表。

因此,需要使用[System.Collections.Hashtable]构造函数重载,该重载允许指定键相等比较方法,以便您指定区分文化,不区分大小写的相等比较器匹配PowerShell的通常哈希表行为 [1]

# PSv5+ syntax
$hashtable = [hashtable]::new(100, [StringComparer]::CurrentCultureIgnoreCase)

# PSv4- syntax
$hashtable = New-Object hashtable 100, ([StringComparer]::CurrentCultureIgnoreCase)

PetSerAl提供以下选择:

$hashtable = [System.Collections.Specialized.CollectionsUtil]::CreateCaseInsensitiveHashtable(100)

另外,正如PetSerAl指出的那样, PowerShell 缓存当前会话的键相等比较器-因此,当前文化的会话内更改被忽略了。 > 。如果要模拟这种可疑的行为,PetSerAl提供以下命令:

$hashtable = [hashtable]::new(100,
 [hashtable].GetProperty(
   'EqualityComparer',
   [System.Reflection.BindingFlags]'NonPublic, Instance'
 ).GetValue(@{}))

尽管使用反射来访问非公共属性,但是这种方法应该是安全的,因为目标属性的访问修饰符为protected,这意味着它具有一个与派生的公共类“签订合同”,不会消失。


请注意,优化哈希表的另一种方法是指定其负载因子,并且还存在用于指定该因子的构造函数重载。

来自the docs(添加了重点):

  

哈希表的容量用于根据负载因子计算哈希表存储桶的最佳数量。容量会根据需要自动增加。

     

负载系数是元素与存储桶的最大比率。较小的加载因子意味着更快的查找速度,但会增加内存消耗。

     

当实际负载系数达到指定的负载系数时,铲斗数将自动增加到最小素数,该最小素数大于当前铲斗数的两倍。


[1]请注意,在许多情况下,PowerShell使用不变文化进行字符串操作,但哈希表似乎是一个例外-请参见this GitHub issuethis answer
The source code揭示了在PowerShell哈希表构造函数中使用CurrentCultureIgnoreCase