今天翻閱《Labuladuo的算法小抄》時發現在使用優先隊列的PriorityQueue解決一道hard題時(leetCode 23),出現了如下代碼:
ListNode mergeKLists(ListNode[] lists) { if (lists.length == 0) return null; // 虛擬頭結點
ListNode dummy = new ListNode(-1); ListNode p = dummy; // 優先級隊列,最小堆
PriorityQueue<ListNode> pq = new PriorityQueue<>( lists.length, (a, b)->(a.val - b.val)); // 將 k 個鏈表的頭結點加入最小堆
for (ListNode head : lists) { if (head != null) pq.add(head); } while (!pq.isEmpty()) { // 獲取最小節點,接到結果鏈表中
ListNode node = pq.poll(); p.next = node; if (node.next != null) { pq.add(node.next); } // p 指針不斷前進
p = p.next; } return dummy.next; }
代碼中出現了 PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, (a, b)->(a.val - b.val));
而在查看PriorityQueue源碼時:
看到PriorityQueue的初始化參數其實是Comparator,也就是在書上的代碼在此處使用了Lambda代替了Comparator.
但為什么可以這樣處理呢?在查找源碼后我發現了,最終在最小堆中的比較會映射到siftUpUsingComparator中的Comparator.compare(x,(E)e):
也就是說我們在插入節點,建堆時使用的比較就是Comparator.compare(),而底層已經默認了使用正負來比較大小。因此使用Lambda方法將(a,b)作為參數返回a.val-b.val 用來代替compare方法是可行的。