<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文看懂.NET6 中的 PriorityQueue

          共 5923字,需瀏覽 12分鐘

           ·

          2021-04-14 12:22

          .NET6 中的 PriorityQueue

          Intro

          .NET 6 中引入了一個(gè)新的集合類(lèi)型 PriorityQueue,正如它的名字那樣,在普通的 Queue 基礎(chǔ)之上增加了優(yōu)先級(jí)的支持,接下來(lái)就一起來(lái)看一下怎么使用,以及一些常用的使用場(chǎng)景介紹。

          Get Started

          來(lái)看一個(gè)簡(jiǎn)單的使用示例:

          var priorityQueue = new PriorityQueue<stringint>();
          priorityQueue.Enqueue("Alice"100);
          priorityQueue.EnqueueRange(Enumerable.Range(15)
              .Select(x => ($"X_{x}"100 - x))
          );

          while (priorityQueue.TryDequeue(out var element, out var priority))
          {
              Console.WriteLine($"Element:{element}{priority}");
          }

          輸出示例:

          可以看到輸出的順序和我們添加的順序是相反的, PriorityQueueDequeue 的時(shí)候是從優(yōu)先級(jí)最小開(kāi)始的,值越小優(yōu)先級(jí)越高,優(yōu)先級(jí)越高越優(yōu)先輸出,如果我們希望最大先輸出是不是可以呢,答案是肯定的,只是我們需要指定我們自己的優(yōu)先級(jí)比較規(guī)則就可以了,可以參考后面的示例

          Scenes

          借助帶優(yōu)先級(jí)的自動(dòng)排序,我們可以做一些自動(dòng)排序的需求的時(shí)候可以考慮使用 PriorityQueue

          Message Queue

          借助 PriorityQueue 可以來(lái)實(shí)現(xiàn)一個(gè)優(yōu)先級(jí)消息隊(duì)列,允許用戶(hù)在發(fā)消息的時(shí)候指定一個(gè)消息的優(yōu)先級(jí),在消費(fèi)的時(shí)候就會(huì)按優(yōu)先級(jí)

          var random = new Random();

          var queue = new PriorityQueue<stringint>();
          for (var i = 1; i <= 10; i++)
          {
              queue.Enqueue($"Message_{i}", random.Next(10100));
          }

          while (queue.TryDequeue(out var message, out _))
          {
              Console.WriteLine(message);
          }

          在上面的示例里我們默認(rèn)指定了一個(gè) int 作為 Priority 的類(lèi)型,并入隊(duì)了一些消息,但是往往會(huì)有很多的消息,可能會(huì)出現(xiàn)優(yōu)先級(jí)相同的情況,我們可以使用時(shí)間和int 作為一個(gè)聯(lián)合的 Priority 類(lèi)型,可以參考下面的示例:

          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(510)));
              }
          }

          while (queue.TryDequeue(out var message, out var priority))
          {
              Console.WriteLine($"{message}{priority.priority}{priority.time}");
          }

          輸出示例如下:

          由上面的結(jié)果可以看出來(lái),在 priority 一樣的情況下,我們會(huì)先處理時(shí)間較小的消息,也可以根據(jù)自己的需要進(jìn)行定制排序方式,自定義 Priority 比較邏輯即可,上面的自定義優(yōu)先級(jí)比較代碼如下:
          internal class DateTimePriorityComparer : IComparer<(DateTime timeint priority)>
          {
              public int Compare((DateTime time, int priority) x, (DateTime time, int priority) y)
              {
                  var priorityComparison = x.priority.CompareTo(y.priority);
                  if (priorityComparison != 0return priorityComparison;
                  return x.time.CompareTo(y.time);
              }
          }

          Rank

          在很多做排行榜的應(yīng)用中也可以使用 PriorityQueue 來(lái)實(shí)現(xiàn),比如我們來(lái)做一個(gè)學(xué)生成績(jī)的排名

          來(lái)看下面的示例代碼:

          var list = new List<(string name, int score)>
          {
              ("Mike"99),
              ("Ming"100),
              ("Jane"96),
              ("Yi"94),
              ("Harry"90),
          };

          var priorityQueue = new PriorityQueue<stringint>();
          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<stringint>(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 就是一個(gè)成績(jī)清單,隨便寫(xiě)了幾個(gè)測(cè)試數(shù)據(jù),通過(guò) PriorityQueueUnorderedItems 我們可以拿到排序之前的數(shù)據(jù),也是我們加入隊(duì)列(Enqueue)的順序,默認(rèn)的比較是小的在前,也就是成績(jī)低的在前,那我們想按從大到小排序的話(huà)就需要自定義比較方式。

          上面的 High2LowComparer 就是一個(gè)自定義的比較,其實(shí)就是把比較的結(jié)果取了一個(gè)反,代碼如下:

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

          上面的輸出結(jié)果如下:

          More

          Redis 里有一個(gè) zset(sortedSet) 類(lèi)型的數(shù)據(jù)也可以做類(lèi)似的事情,但是 zset 和 PriorityQueue 還是有一些不同的,zset 是一個(gè) set,是一個(gè)自動(dòng)去重的集合,而 PriorityQueue 還是一個(gè) Queue 不會(huì)去重,zset 可以修改對(duì)應(yīng)元素的 priority(score),但是 PriorityQueue 目前不支持修改元素對(duì)應(yīng)的優(yōu)先級(jí)

          PriorityQueue  可以解決我們的一些問(wèn)題,但是有一些使用要注意的地方:

          1. 首先如果 Priority 是一樣的話(huà),輸出的順序是有可能不一樣的,這是由它內(nèi)部的實(shí)現(xiàn)算法決定的,不能?chē)?yán)格的保證順序
          2. PriorityQueue 是非線程安全的,需要注意線程安全問(wèn)題
          3. PriorityQueue 中的 Peek 方法只會(huì)獲取 queue 里即將出隊(duì)的元素,但是不會(huì)從隊(duì)列中移除這個(gè)元素

          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







          回復(fù) 【關(guān)閉】學(xué)關(guān)
          回復(fù) 【實(shí)戰(zhàn)】獲取20套實(shí)戰(zhàn)源碼
          回復(fù) 【被刪】學(xué)個(gè)
          回復(fù) 【訪客】學(xué)
          回復(fù) 【小程序】學(xué)獲取15套【入門(mén)+實(shí)戰(zhàn)+賺錢(qián)】小程序源碼
          回復(fù) 【python】學(xué)微獲取全套0基礎(chǔ)Python知識(shí)手冊(cè)
          回復(fù) 【2019】獲取2019 .NET 開(kāi)發(fā)者峰會(huì)資料PPT
          回復(fù) 【加群】加入dotnet微信交流群


          人人影視字幕組涼了,這款美劇APP不能錯(cuò)過(guò)!


          谷歌靈魂插件,98%的程序員都好評(píng)!


          瀏覽 125
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产无码免费在线观看 | 亚洲无码高清在线视频 | 日老逼 | 亚洲欧美在线视频 | 精品久久乐|