空哈希集 - 计数与任意

问题描述 投票:0回答:3

我只想知道 HashSet

hs
是否为空。 我没兴趣知道它到底包含多少元素。

所以我可以用这个:

bool isEmpty = (hs.Count == 0);

...或者这个:

bool isEmpty = hs.Any(x=>true);

哪一个在性能方面提供更好的结果(特别是当 HashSet 包含大量元素时)?

c# .net performance hashset
3个回答
20
投票

在 HashSet 上,您可以同时使用两者,因为 HashSet 内部管理计数。

但是,如果您的数据位于

IEnumerable<T>
IQueryable<T>
对象中,则使用
result.Any()
优于
result.Count()
(两种 Linq 方法)。

Linq 的

.Count()
将迭代整个 Enumerable,
.Any()
只会查看 Enumerable 中是否存在任何对象。

更新: 只是小补充: 在您使用 HashSet 的情况下,

.Count
可能更可取,因为
.Any()
需要创建并返回
IEmumerator
,如果您不打算在代码中的任何地方使用枚举器(
foreach
,林克等)。但我认为这将被视为“微优化”。

更新2 很长一段时间后重新审视它,在 .NET Core 的情况下,这有点棘手,但在

IEnumerabel<T>
的情况下。如果
IEnumerable<T>
是一个 HashSet 或集合,
.Any()
将检查它的基础类型,并在调用时应用
.Count
(如果它是
ICollection<T>
类型),如果它确定它具有
.Count
属性,否则将循环通过可枚举来计数。

来源:.NET Core 运行时


4
投票

HastSet<T>
实现了
ICollection<T>
,它具有
Count
属性,因此对
Count()
的调用只会调用
HastSet<T>.Count
,我假设这是一个 O(1) 操作(这意味着它实际上并不必须 count - 它只返回
HashSet
的当前大小。

Any
将迭代,直到找到与条件匹配的项目,然后停止。

所以在你的情况下,它只会迭代一项,然后停止,所以差异可能可以忽略不计

如果您想要应用一个过滤器(例如

x => x.IsValid
),那么
Any
肯定更快,因为
Count(x => x.IsValid)
会迭代整个集合,而
Any
会立即停止,如果找到匹配项。

出于这些原因,我通常更喜欢使用

Any()
而不是
Count()==0
,因为它更直接并且可以避免任何潜在的性能问题。如果它比
Count()==0
提供了显着性能提升,我只会切换到
Any()

请注意,

Any(x=>true)
在逻辑上与调用
Any()
相同。这不会改变你的问题,但没有 lambda 看起来更干净。


0
投票

根据集合的类型,它可能会或可能不会影响性能。那么为什么不直接使用

hs.Any()
因为它正是为您需要了解的内容而设计的呢?

并且 lambda 表达式

x => true
在这里没有任何意义。你可以忽略它。

© www.soinside.com 2019 - 2024. All rights reserved.