杰伦·莫斯特 https://stackoverflow.com/users/4137916/jeroen-mostert很好地说明了为什么你可能不这样做need指定初始容量:
请注意,预先指定容量通常不会在内存或运行时间方面为您带来太多好处;它已经实现了慷慨的动态调整,如果你的猜测不正确,那么好处基本上就会消失。
如果您确实需要指定初始容量:
Tip of the hat to PetSerAl https://stackoverflow.com/users/4003407/petseral for his help.
因为 PowerShell 哈希表总是不区分大小写关于关键查找,[hashtable]::new(100)
does not不幸的是,工作,因为默认是创建一个案例 -敏感的哈希表。
Therefore, use of a [System.Collections.Hashtable]
constructor overload that allows specifying the key-equality comparison method is required, so that you can specify a culture-sensitive, case-insensitive equality comparer to match PowerShell's usual hashtable behavior in v6.1-[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)
注:在v6.2+电源外壳现在使用一个ordinal字符串比较器 ([StringComparer]::OrdinalIgnoreCase
).
此外,正如 PetSerAl 指出的那样,PowerShell v6.1-caches当前会话的关键平等比较器 - 因此当前文化的会话中更改是ignored。如果您想模拟这种有问题的行为,PetSerAl 提供了以下命令:
$hashtable = [hashtable]::new(100,
[hashtable].GetProperty(
'EqualityComparer',
[System.Reflection.BindingFlags]'NonPublic, Instance'
).GetValue(@{}))
Despite the use of reflection to access a non-public property, this approach should be safe, because the targeted property's access modifier is protected
, which means it has a "contract" with derived public classes and won't go away.
请注意,优化哈希表的另一种方法是指定其负载系数,并且还有用于指定该因子的构造函数重载。
From the docs https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable.-ctor#System_Collections_Hashtable__ctor(强调):
哈希表的capacity用于根据负载因子计算哈希表桶的最佳数量。容量会根据需要自动增加。
The 负载系数是元素与桶的最大比率。较小的负载因子意味着更快的查找,但会增加内存消耗。
当实际负载率达到指定负载率时,桶数自动增加到大于当前桶数两倍的最小素数。
[1] Note that in many contexts PowerShell uses the invariant culture for string operations, but hashtables seem to be an exception - see this GitHub issue https://github.com/PowerShell/PowerShell/issues/8280 and this answer https://stackoverflow.com/a/37603732/45375.
The v6.1- source code https://github.com/PowerShell/PowerShell/blob/877b9a9fbf0bed3876de3c00ff34525aba96c749/src/System.Management.Automation/engine/parser/Compiler.cs#L5694-L5696 reveals the use of CurrentCultureIgnoreCase
in PowerShell's hashtable constructor, and the v6.2+ source code https://github.com/PowerShell/PowerShell/blob/1e5655b48cdad707ee3678435c4b587c0856a35c/src/System.Management.Automation/engine/parser/Compiler.cs#L6442-L6444 now shows use of ordinal (case-insensitive) comparison.