.NET6 中的 PriorityQueue

.NET6 中的 PriorityQueue

Intro

.NET 6 中引入了一个新的集合类型 PriorityQueue,正如它的名字那样,在普通的 Queue 基础之上增加了优先级的支持,接下来就一起来看一下怎么使用,以及一些常用的使用场景介绍。

Get Started

来看一个简单的使用示例:

var priorityQueue = new PriorityQueue<string, int>();
priorityQueue.Enqueue("Alice", 100);
priorityQueue.EnqueueRange(Enumerable.Range(1, 5).Select(x => ($"X_{x}", 100 - x))
);while (priorityQueue.TryDequeue(out var element, out var priority))
{Console.WriteLine($"Element:{element}, {priority}");
}

输出示例:

可以看到输出的顺序和我们添加的顺序是相反的, PriorityQueueDequeue 的时候是从优先级最小开始的,值越小优先级越高,优先级越高越优先输出,如果我们希望最大先输出是不是可以呢,答案是肯定的,只是我们需要指定我们自己的优先级比较规则就可以了,可以参考后面的示例

Scenes

借助带优先级的自动排序,我们可以做一些自动排序的需求的时候可以考虑使用 PriorityQueue

Message Queue

借助 PriorityQueue 可以来实现一个优先级消息队列,允许用户在发消息的时候指定一个消息的优先级,在消费的时候就会按优先级

var random = new Random();var queue = new PriorityQueue<string, int>();
for (var i = 1; i <= 10; i++)
{queue.Enqueue($"Message_{i}", random.Next(10, 100));
}while (queue.TryDequeue(out var message, out _))
{Console.WriteLine(message);
}

在上面的示例里我们默认指定了一个 int 作为 Priority 的类型,并入队了一些消息,但是往往会有很多的消息,可能会出现优先级相同的情况,我们可以使用时间和int 作为一个联合的 Priority 类型,可以参考下面的示例:

var random = new Random();var queue = new PriorityQueue<string, (DateTime time, int priority)>(new DateTimePriorityComparer());var time = DateTime.UtcNow;
Thread.Sleep(1000);
for (var k = 0; k < 3; k++)
{for (var i = 1; i <= 3; i++){queue.Enqueue($"Message_{i}_{k}", (i > 2 ? time : DateTime.UtcNow, random.Next(5, 10)));}
}while (queue.TryDequeue(out var message, out var priority))
{Console.WriteLine($"{message}, {priority.priority}, {priority.time}");
}

输出示例如下:

由上面的结果可以看出来,在 priority一样的情况下,我们会先处理时间较小的消息,也可以根据自己的需要进行定制排序方式,自定义 Priority 比较逻辑即可,上面的自定义优先级比较代码如下:
internal class DateTimePriorityComparer : IComparer<(DateTime time, int priority)>
{public int Compare((DateTime time, int priority) x, (DateTime time, int priority) y){var priorityComparison = x.priority.CompareTo(y.priority);if (priorityComparison != 0) return priorityComparison;return x.time.CompareTo(y.time);}
}

Rank

在很多做排行榜的应用中也可以使用 PriorityQueue 来实现,比如我们来做一个学生成绩的排名

来看下面的示例代码:

var list = new List<(string name, int score)>
{("Mike", 99),("Ming", 100),("Jane", 96),("Yi", 94),("Harry", 90),
};var priorityQueue = new PriorityQueue<string, int>();
priorityQueue.EnqueueRange(list);Console.WriteLine("--Unordered:");
foreach (var item in priorityQueue.UnorderedItems)
{Console.WriteLine($"Name:{item.Element}, score:{item.Priority}");
}Console.WriteLine("--Ordered:");
while (priorityQueue.TryDequeue(out var name, out var score))
{Console.WriteLine($"Name:{name}, score:{score}");
}Console.WriteLine("-----TOP 3");
priorityQueue = new PriorityQueue<string, int>(new High2LowComparer());
priorityQueue.EnqueueRange(list);
var rank = 0;
while (rank++ < 3 && priorityQueue.TryDequeue(out var name, out var score))
{Console.WriteLine($"Rank({rank}):Name:{name}, score:{score}");
}

上面的 list 就是一个成绩清单,随便写了几个测试数据,通过 PriorityQueueUnorderedItems 我们可以拿到排序之前的数据,也是我们加入队列(Enqueue)的顺序,默认的比较是小的在前,也就是成绩低的在前,那我们想按从大到小排序的话就需要自定义比较方式。

上面的 High2LowComparer 就是一个自定义的比较,其实就是把比较的结果取了一个反,代码如下:

internal class High2LowComparer : IComparer<int>
{public int Compare(int x, int y){return y.CompareTo(x);}
}

上面的输出结果如下:

More

Redis 里有一个 zset(sortedSet) 类型的数据也可以做类似的事情,但是 zset 和 PriorityQueue 还是有一些不同的,zset 是一个 set,是一个自动去重的集合,而 PriorityQueue 还是一个 Queue 不会去重,zset 可以修改对应元素的 priority(score),但是 PriorityQueue 目前不支持修改元素对应的优先级

PriorityQueue  可以解决我们的一些问题,但是有一些使用要注意的地方:

  1. 首先如果 Priority 是一样的话,输出的顺序是有可能不一样的,这是由它内部的实现算法决定的,不能严格的保证顺序

  2. PriorityQueue 是非线程安全的,需要注意线程安全问题

  3. PriorityQueue 中的 Peek 方法只会获取 queue 里即将出队的元素,但是不会从队列中移除这个元素

References

  • https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-2/

  • https://github.com/dotnet/runtime/blob/v6.0.0-preview.2.21154.6/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/PriorityQueueSample/Program.cs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单而不简陋﹣wp7视觉点滴

一直就很期待&#xff0c;引入了Metro设计理念的wp7的真实操作体验&#xff0c;现在终于如愿了。拿到测试机&#xff0c;首先迅速的过了一遍&#xff0c;第一印象就是界面简单明了&#xff0c;没有华丽的高光、没有跌宕的质感&#xff0c;真的感觉就像在公共场所看到的信息指示…

ros发布节点信息python_vscode开发ROS1(13)-python实现话题通信(msg)

写在最前面1, ros也是可以使用python进行编程的, 而且相比c来说, ros更加简单.使用python创建第一个ROS程序1, 在ros_test目录下, 新建一个scripts文件夹.2, 修改CMakeLists.txt文件, 在find_package中添加rospyfind_package(catkin REQUIRED COMPONENTS roscpp ... #其他的包 …

BeetleX 之 WebApi网关1.5.8发布

这一版本的主要升级了BeetleX的基础网络库&#xff0c;主要解决在某些情况导致解释http协议cpu暴增长的问题&#xff0c;同时使用BeetleX新版本针对的IndexOf的优化&#xff0c;使http协议解释上有着一定程度的性能提升。新版本同样也是支持win64和linux64两个版本&#xff0c;…

egg前面加什么_国威说阀:阀门前面为什么加国标美标日标之类的?

原标题&#xff1a;国威说阀&#xff1a;阀门前面为什么加国标美标日标之类的&#xff1f;美标阀门就是美国标准的意思&#xff0c;通常称呼的美标球阀&#xff0c;美标闸阀和其它什么阀门都是按照美国标准制造出来的阀门其中一类。标准的编制说明是一个非常重要的文件。它阐明…

读《有效需求分析》

最近在一个技术群里看到张逸大佬强力推荐一本关于需求分析的书《有效需求分析》&#xff0c;于是在 Kindle 上下单了&#xff0c;读完后有一种相见恨晚的感觉。本书特点从书中的一些案例可以看出&#xff0c;作者擅长 ToB 软件的需求分析&#xff0c;如果您是从事的 ToB 软件的…

超时锁定计算机,就会发现多了一个控制台锁定显示关闭超时选项

小技巧&#xff1a;锁定屏幕方法多在临时要离开电脑时&#xff0c;可用CtrlAltDel组合键、WinL组合键或在开始菜单中单击用户头像选择“锁定”手动锁屏;或借用“屏幕保护设置”设定自动定时锁屏。1. 探寻自动锁屏时间修改离开电脑一段时间后Windows 10会自动锁屏&#xff0c;但…

android数据存放map_ES6 的新鲜玩意儿——集合set、map、WeekSet、WeekMap

es6新增了Set、Map、WeekSet、WeekMap 四种数据结构。C#中有HashSet和Dictionary&#xff0c;HashSet和Dictionary都是范式集合&#xff0c;但是es6不支持接口开发&#xff0c;所以也就不存在范式。Set 是存唯一值的集合&#xff0c;Map是存键值对的集合。WeakSet、WeakMap分别…

大牛领导单独找我聊了两句:搞框架的同时别忘了算法

前言程序数据结构算法&#xff0c;好的算法能让程序更高效的运行&#xff1b;在当今数据信息时代&#xff0c;数据分析和数据处理肯定是避免不了&#xff0c;而算法便成为了很多公司门槛级的要求&#xff0c;特别是大厂&#xff1b;赶紧搞起来&#xff0c;说不定离进大厂就只差…

C#使用iTextSharp操作PDF文件

概述html文件怎么转成PDF文件&#xff1f;有的招聘网上的简历导成DOC文件&#xff0c;不能直接使用&#xff0c;这样造成很大的困扰&#xff0c;那么它还有一个格式&#xff0c;那就是html格式。将文件导出成html格式&#xff0c;然后再转成PDF文件&#xff0c;这样便可以直接使…

springboot 历史版本文档_Springboot看视频学太慢?来看看这份阿里深入实践Springboot文档...

前言&#xff1a;之前 Spring Boot 2.2没能按时发布&#xff0c;是由于 Spring Framework 5.2 的发布受阻而推迟。这次随着 Spring Framework 5.2.0 成功发布之后&#xff0c;Spring Boot 2.2 也紧跟其后&#xff0c;发布了第一个版本&#xff1a;2.2.0。关于Spring Boot的性能…

51CTO技术沙龙4月23日第四期:如何快速定位******

人 在江湖飘&#xff0c;哪能不挨刀&#xff1f;没有跟***打过交道的运维人员能有多少&#xff1f;恐怕工作时间长的朋友大多都遇到过。我们除了做好防御之外&#xff0c;也可以尝试着像“盗梦空间”那 样了解******的动向。也可以从追踪***到挖掘***隐藏技术。当然&#xff0c…

计算机软件损坏基本维修,学习修电脑基础没有用?客户电脑开机不显示,维修差点被坑!...

原标题&#xff1a;学习修电脑基础没有用&#xff1f;客户电脑开机不显示&#xff0c;维修差点被坑&#xff01;电脑故障分为硬件故障与软件故障&#xff0c;硬件故障指的是硬件损坏&#xff0c;软件故障指的是系统损坏&#xff0c;硬件故障还可以分为真坏与假坏&#xff0c;真…

cass小插件集合_插件|如何精准提取CASS方格网高程点?

CASS的方格网土方计算时&#xff0c;在格网上会内插很多高程点&#xff0c;下图所示的黄色、蓝色和洋红色的高程点。怎么能批量提取这些点呢&#xff1f;CASS方格网截图CASS升级到10.1之后&#xff0c;增加了一个菜单&#xff1a;工程应用-注记生成数据文件。这个功能可以将文字…

使用.NET开发的数据库小工具 DbTool

数据库小工具 DbToolIntroDbTool 一个支持 DbFirst、ModelFirst 和 CodeFirst 的数据库小工具。DbFirst 是根据数据库中的表信息生成代码中的 Model&#xff0c;以及生成数据表结构文档ModelFirst 是根据数据表信息或者数据表结构文档生成创建数据库的脚本CodeFirst 是指根据 m…

古登堡是垂直搜索引擎吗_网站排名,提高内容输出频率,就一定要对排名好吗?-SEO...

如果你在长期做百度SEO一定会有这样一个明显的感觉&#xff0c;通过每天大量的输出相关性的内容&#xff0c;实际上是有利于提高网站的抓取频率与整站的权重。 而对于百度搜索引擎而言&#xff0c;对方也确实有这么一个考量&#xff0c;用于衡量一个网站的活跃度与覆盖搜索需求…

Windows环境下Dapr入门

Dapr是Distributed Application Runtime&#xff08;分布式应用运行时&#xff09;的缩写。它是一个可移植的、事件驱动的运行时。下面介绍如何在Windows平台安装Dapr&#xff1a;安装Dapr CLIDapr CLI是使用Dapr相关功能的主要工具&#xff0c;您可以使用它来以Dapr Sidecar的…

linq查询不包含某个值的记录_【翻译】C#表达式中的动态查询

当您使用LINQ来处理数据库时&#xff0c;这种体验是一种神奇的体验&#xff0c;对吗&#xff1f;你把数据库实体像一个普通的收集&#xff0c;使用Linq中像Where&#xff0c;Select或者 Take&#xff0c;这些简单的使用就能让代码可用了。但是&#xff0c;让我们考虑一下这里是…

计算机二级ppt为客户制作演示文稿,计算机二级ppt真题:制作介绍北京ppt

1.演示文稿题1具体如图示。2.【打开】文件夹&#xff0c;选择【PPT素材.docx】&#xff0c;点击【选择】选定所有格式类似的文本(无数据)&#xff0c;点击【段落】&#xff0c;调整【大纲级别】1级。选择【蓝色文本】&#xff0c;点击【选择】选定所有格式相似的文本(无数据)&a…

牛气!.NET5电商平台轻松承接10亿GMV,只因做对了这个!

自从京东和唯品会转了Java..NET就一直缺乏高并发电商案例&#xff0c;.NET5能做高并发电商吗&#xff1f;必须的&#xff01;这里为大家分享一家上市电商公司项目案例&#xff1a;纯.NET5电商平台&#xff0c;轻松承接双11当天近10亿GMV&#xff01;系统架构为.NET5微服务Docke…

项目进度计划甘特图_项目管理进度计划表制作及甘特图绘制方法

全文总计1995字&#xff0c;需阅读5分钟&#xff0c;以下为正文&#xff1a;甘特图(Gantt Chart)又称横道图&#xff0c;它通过图示形象地表示特定项目的活动顺序与持续时间。Excel 2007/2010中&#xff0c; 通过堆积条形图实现。下面以Excel 2010为例来说明绘制步骤上图A列为某…