具有初始容量的 Powershell 哈希表

Powershell Hashtable with Initial Capacity

我想知道您如何在 powershell 中声明具有初始容量的哈希表。我知道我想要它有多大,但我必须在循环中为它分配值。

所以像这样:

$hashtable = @{} (100)

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

Be aware that pre-specifying the capacity usually doesn't win you much in terms of memory or runtime, though; it already implements generous dynamic sizing, and if your guess is off, the benefits basically evaporate.

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

PetSerAl 致敬。

因为 PowerShell 的哈希表在键查找方面总是不区分大小写[hashtable]::new(100) 工作,不幸的是,因为默认是创建一个 case-sensitive hashtable.

因此,需要使用允许指定键相等比较方法的 [System.Collections.Hashtable] 构造函数重载,以便您可以指定区分区域性、不区分大小写的相等比较器 以匹配 PowerShell 在 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+ PowerShell 现在使用 序数 字符串比较器 ( [StringComparer]::OrdinalIgnoreCase).

此外,正如 PetSerAl 指出的那样,PowerShell v6.1- 缓存 当前会话的密钥相等性比较器 - 因此会话中更改当前文化被 忽略。如果您想模拟这种有问题的行为,PetSerAl 提供了以下命令:

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

尽管使用反射来访问非public属性,这种方法应该是安全的,因为有针对性属性 的访问修饰符是 protected,这意味着它与派生的 public 类 有一个“契约”,并且不会消失。


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

来自 the docs(已强调):

A hash table's capacity is used to calculate the optimal number of hash table buckets based on the load factor. Capacity is automatically increased as required.

The load factor is the maximum ratio of elements to buckets. A smaller load factor means faster lookup at the cost of increased memory consumption.

When the actual load factor reaches the specified load factor, the number of buckets is automatically increased to the smallest prime number that is larger than twice the current number of buckets.


[1] 请注意,在许多情况下,PowerShell 使用 不变文化 进行字符串操作,但哈希表似乎是一个例外 - 请参阅 this GitHub issue and this answer.
The v6.1- source code reveals the use of CurrentCultureIgnoreCase in PowerShell's hashtable constructor, and the v6.2+ source code 现在显示使用 ordinal(不区分大小写)比较。