热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么HashSet<T>类不用于实现Enumerable.Distinct

如何解决《为什么HashSet<T>类不用于实现Enumerable.Distinct》经验,为你挑选了1个好方法。

我需要访问IEnumerable.Distinct大O表示法 的渐近时间和空间复杂度

所以我在看扩展方法的实现,Enumerable.Distinct我看到它是使用和内部类实现的Set,这几乎是一个带有"开放寻址"的哈希表的经典实现

很快引起注意的是,很多代码Set只是一个复制粘贴HashSet,有一些遗漏

但是,这种简化的Set实现有一些明显的缺陷,例如Resize不使用素数作为插槽大小的方法,就像HashSet看到的那样,请参阅HashHelpers.ExpandPrime

所以,我的问题是:

    这里代码重复的原因是什么,为什么不坚持DRY原则?特别是考虑到这两个类都在同一个程序集中System.Core

    它看起来HashSet会表现得更好,所以我应该避免使用Distinct扩展方法,并编写我自己的扩展方法,HashSet而不是使用Set

Jon Hanna.. 6

这几乎是具有"开放寻址"的哈希表的经典实现

再看一遍.它与列表头单元格分开链接.虽然插槽都在一个阵列中,但在碰撞情况下找到下一个插槽是通过检查next当前插槽的字段来完成的.这比使用链接列表和每个节点作为单独的堆对象具有更好的缓存效率,但在这方面不如开放寻址那么好.同时,它避免了一些开放式寻址效果不佳的情况.

Set中的很多代码只是来自HashSet的复制粘贴,有一些遗漏

AFAICT使用哈希集的私有实现的原因是Enumerable并且HashSet几乎在同一时间独立开发.这只是我的猜想,但它们都是用.NET 3.5引入的,所以它是可行的.

很可能HashSet从复制开始Set,然后更好地公开曝光,尽管这两者都可能都基于与列表头单元格分开链接的相同原则

在性能方面,HashSet使用素数意味着它更有可能避免与较差的哈希冲突(但这只是一个优势,这不是一个简单的问题),但Set在很多方面更轻,特别是在.NET中核心,其中不需要的东西被删除.特别是,该版本Set采用的事实,即一旦一个项目被删除(这情况发生,例如,在优势Intersect),永远不会有新增项目,这使得它能够省去freelist与此相关的任何工作,这HashSetcouldn"做.即使是最初的实施也没有跟踪版本以便在枚举期间捕获变化,这是一个很小的成本,但是每次添加和删除的成本都是如此.

因此,对于具有不同哈希码分布的不同数据集,有时一个表现更好,有时另一个表现更好.

特别是考虑到这两个类都在同一个程序集System.Core中

仅在某些版本的.NET中,在某些版本中,它们位于不同的程序集中.在.NET Core中,我们有两个版本Set,一个在程序System.Linq集中,另一个在单独的程序集中System.Linq.Expressions.前者如上所述被削减,后者被替换为使用,HashSet因为它在那里做得少.

当然System.Core是第一位的,但是这些元素可以完全分开的事实说明System.Core不是一个单一依赖关系的整体blob.

现在有一种ToHashSet()方法在.NET核心的版本的LINQ使得更换的可能性SetHashSet更合理的,虽然不是没有脑子.我认为@james-ko正在考虑测试这样做的好处.

它看起来HashSet会表现得更好

由于上面解释的原因,情况可能并非如此,但可能确实如此,具体取决于源数据.这是在考虑经过一些不同的linq方法的优化之前(在linq的初始版本中并不多,但在.NET Core中很少).

所以我应该避免使用Distinct扩展方法,并编写我自己的扩展方法,HashSet而不是使用Set.

使用Distinct().如果你有一个瓶颈,那么它可能HashSet会在给定的数据集中获胜,但是如果你确实尝试这样做,请确保你的分析与你的代码在现实生活中会遇到的实际值非常接近.没有必要决定一种方法是基于某些任意测试更快,如果你的应用程序遇到另一个做得更好的情况.(如果我发现这是一个问题点,我会先看看有问题GetHashCode()的类型是否可以改进速度或比特分配,首先).



1> Jon Hanna..:

这几乎是具有"开放寻址"的哈希表的经典实现

再看一遍.它与列表头单元格分开链接.虽然插槽都在一个阵列中,但在碰撞情况下找到下一个插槽是通过检查next当前插槽的字段来完成的.这比使用链接列表和每个节点作为单独的堆对象具有更好的缓存效率,但在这方面不如开放寻址那么好.同时,它避免了一些开放式寻址效果不佳的情况.

Set中的很多代码只是来自HashSet的复制粘贴,有一些遗漏

AFAICT使用哈希集的私有实现的原因是Enumerable并且HashSet几乎在同一时间独立开发.这只是我的猜想,但它们都是用.NET 3.5引入的,所以它是可行的.

很可能HashSet从复制开始Set,然后更好地公开曝光,尽管这两者都可能都基于与列表头单元格分开链接的相同原则

在性能方面,HashSet使用素数意味着它更有可能避免与较差的哈希冲突(但这只是一个优势,这不是一个简单的问题),但Set在很多方面更轻,特别是在.NET中核心,其中不需要的东西被删除.特别是,该版本Set采用的事实,即一旦一个项目被删除(这情况发生,例如,在优势Intersect),永远不会有新增项目,这使得它能够省去freelist与此相关的任何工作,这HashSetcouldn"做.即使是最初的实施也没有跟踪版本以便在枚举期间捕获变化,这是一个很小的成本,但是每次添加和删除的成本都是如此.

因此,对于具有不同哈希码分布的不同数据集,有时一个表现更好,有时另一个表现更好.

特别是考虑到这两个类都在同一个程序集System.Core中

仅在某些版本的.NET中,在某些版本中,它们位于不同的程序集中.在.NET Core中,我们有两个版本Set,一个在程序System.Linq集中,另一个在单独的程序集中System.Linq.Expressions.前者如上所述被削减,后者被替换为使用,HashSet因为它在那里做得少.

当然System.Core是第一位的,但是这些元素可以完全分开的事实说明System.Core不是一个单一依赖关系的整体blob.

现在有一种ToHashSet()方法在.NET核心的版本的LINQ使得更换的可能性SetHashSet更合理的,虽然不是没有脑子.我认为@james-ko正在考虑测试这样做的好处.

它看起来HashSet会表现得更好

由于上面解释的原因,情况可能并非如此,但可能确实如此,具体取决于源数据.这是在考虑经过一些不同的linq方法的优化之前(在linq的初始版本中并不多,但在.NET Core中很少).

所以我应该避免使用Distinct扩展方法,并编写我自己的扩展方法,HashSet而不是使用Set.

使用Distinct().如果你有一个瓶颈,那么它可能HashSet会在给定的数据集中获胜,但是如果你确实尝试这样做,请确保你的分析与你的代码在现实生活中会遇到的实际值非常接近.没有必要决定一种方法是基于某些任意测试更快,如果你的应用程序遇到另一个做得更好的情况.(如果我发现这是一个问题点,我会先看看有问题GetHashCode()的类型是否可以改进速度或比特分配,首先).


推荐阅读
  • 如何解决《为什么我会在字典上使用HashSet?》经验,为你挑选了2个好方法。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • Vagrant虚拟化工具的安装和使用教程
    本文介绍了Vagrant虚拟化工具的安装和使用教程。首先介绍了安装virtualBox和Vagrant的步骤。然后详细说明了Vagrant的安装和使用方法,包括如何检查安装是否成功。最后介绍了下载虚拟机镜像的步骤,以及Vagrant镜像网站的相关信息。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 本文讨论了在使用Git进行版本控制时,如何提供类似CVS中自动增加版本号的功能。作者介绍了Git中的其他版本表示方式,如git describe命令,并提供了使用这些表示方式来确定文件更新情况的示例。此外,文章还介绍了启用$Id:$功能的方法,并讨论了一些开发者在使用Git时的需求和使用场景。 ... [详细]
  • 本文介绍了在实现了System.Collections.Generic.IDictionary接口的泛型字典类中如何使用foreach循环来枚举字典中的键值对。同时还讨论了非泛型字典类和泛型字典类在foreach循环中使用的不同类型,以及使用KeyValuePair类型在foreach循环中枚举泛型字典类的优势。阅读本文可以帮助您更好地理解泛型字典类的使用和性能优化。 ... [详细]
  • 从零开始的ESP8266探索(15)WiFi其他方法和WiFi事件响应
    文章目录目的WiFi其他方法WiFi事件响应事件列表注册事件使用示例总结目的WiFi在使用过程中并非会一直如希望般稳定运行的,为了应对这些情况就需要能够了解WiFi ... [详细]
  • 分析OpenSurf(2)
    ①积分图像的实现首先在Integral.cpp里面找到Integral(),如下:IplImage*Integral(IplImage*source) ... [详细]
  • 如何解决《为什么我不能使用HashSet<string>来实现IEnumerable<string>接口属性?》经验,为你挑选了1个好方法。 ... [详细]
  • 如何解决《JavaHashSet包含无法正常工作的函数》经验,为你挑选了1个好方法。 ... [详细]
author-avatar
momosu1028_738_636
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有