有人可以向我解释这个例子中的 PriorityQueue 吗?
Can someone explain PriorityQueue in this example to me?
我正在尝试学习如何使用 PriorityQueue,因为我以前从未使用过。这是我在 LeetCode 上找到的一个正在使用的示例,用于在字符串数组中找到前 K 个元素的问题
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> count = new HashMap();
for (String word: words) {
count.put(word, count.getOrDefault(word, 0) + 1);
}
PriorityQueue<String> heap = new PriorityQueue<String>(
(w1, w2) -> count.get(w1).equals(count.get(w2)) ?
w2.compareTo(w1) : count.get(w1) - count.get(w2) );
for (String word: count.keySet()) {
heap.offer(word);
if (heap.size() > k) heap.poll();
}
List<String> ans = new ArrayList();
while (!heap.isEmpty()) ans.add(heap.poll());
Collections.reverse(ans);
return ans;
}
更值得注意的是,我想知道这条线在做什么:
PriorityQueue<String> heap = new PriorityQueue<String>(
(w1, w2) -> count.get(w1).equals(count.get(w2)) ?
w2.compareTo(w1) : count.get(w1) - count.get(w2) );
谁能用蹩脚的术语解释一下这里发生了什么?有没有办法将比较器重写为常规 "if" 语句?
感谢您的帮助。
您正在使用的 PriorityQueue
构造函数声明为:
public PriorityQueue(Comparator<? super E> comparator)
它接受泛型参数对象的比较器。 comparator
构造函数参数描述为:
the comparator that will be used to order this priority queue. If null, the natural ordering of the elements will be used.
在您的调用中,参数是一个 lambda expression,它提供了实现 Comparator<String>
。它大致等同于以下匿名 class:
PriorityQueue<String> heap2 = new PriorityQueue<String>(new Comparator<String>() {
@Override
public int compare(String w1, String w2) {
if(count.get(w1).equals(count.get(w2))) {
return w2.compareTo(w1);
} else {
return count.get(w1) - count.get(w2);
}
// can also just be (without the if/else above):
//return count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2);
}
});
你在构造函数中的表达式是一个 lambda expression. Because Comparator
是一个函数式接口,也就是说,它是一个只有一个抽象方法的接口,lambda 表达式可以用作 shorthand 用于创建匿名 class.
在你的例子中,
new PriorityQueue<String>((w1, w2) -> count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2));
在功能上等同于
new PriorityQueue<String>(new Comparator<String>() {
public int compare(String w1, String w2) {
return count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2);
}
});
这也等同于创建一个单独的 class 来实现 Comparator<String>
,并将该 class 的一个实例作为参数传递给 PriorityQueue
。
至于将 Comparator
写成 if 语句,简短的回答是,不。比较器必须是 Comparator<String>
的实例。然而,也许同一个比较器的一个更容易理解的版本如下:
new PriorityQueue<String>((w1, w2) -> {
if (count.get(w1).equals(count.get(w2))) { // If the counts of w1 and w2 are the same,
return w2.compareTo(w1); // Then return the reverse lexicographical ordering of w1 and w2 (e.g. "Zebra" comes before "Apple")
} else if (count.get(w1) < count.get(w2)) {
return -1; // w1 comes before w2
} else {
return 1; // w1 comes after w2
}
});
注意:"Lexicographical ordering"本质上是按字母排序,但基于 ASCII 码。有关详细信息,请参阅 String#compareTo(String)
希望对您有所帮助!
我正在尝试学习如何使用 PriorityQueue,因为我以前从未使用过。这是我在 LeetCode 上找到的一个正在使用的示例,用于在字符串数组中找到前 K 个元素的问题
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> count = new HashMap();
for (String word: words) {
count.put(word, count.getOrDefault(word, 0) + 1);
}
PriorityQueue<String> heap = new PriorityQueue<String>(
(w1, w2) -> count.get(w1).equals(count.get(w2)) ?
w2.compareTo(w1) : count.get(w1) - count.get(w2) );
for (String word: count.keySet()) {
heap.offer(word);
if (heap.size() > k) heap.poll();
}
List<String> ans = new ArrayList();
while (!heap.isEmpty()) ans.add(heap.poll());
Collections.reverse(ans);
return ans;
}
更值得注意的是,我想知道这条线在做什么:
PriorityQueue<String> heap = new PriorityQueue<String>(
(w1, w2) -> count.get(w1).equals(count.get(w2)) ?
w2.compareTo(w1) : count.get(w1) - count.get(w2) );
谁能用蹩脚的术语解释一下这里发生了什么?有没有办法将比较器重写为常规 "if" 语句?
感谢您的帮助。
您正在使用的 PriorityQueue
构造函数声明为:
public PriorityQueue(Comparator<? super E> comparator)
它接受泛型参数对象的比较器。 comparator
构造函数参数描述为:
the comparator that will be used to order this priority queue. If null, the natural ordering of the elements will be used.
在您的调用中,参数是一个 lambda expression,它提供了实现 Comparator<String>
。它大致等同于以下匿名 class:
PriorityQueue<String> heap2 = new PriorityQueue<String>(new Comparator<String>() {
@Override
public int compare(String w1, String w2) {
if(count.get(w1).equals(count.get(w2))) {
return w2.compareTo(w1);
} else {
return count.get(w1) - count.get(w2);
}
// can also just be (without the if/else above):
//return count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2);
}
});
你在构造函数中的表达式是一个 lambda expression. Because Comparator
是一个函数式接口,也就是说,它是一个只有一个抽象方法的接口,lambda 表达式可以用作 shorthand 用于创建匿名 class.
在你的例子中,
new PriorityQueue<String>((w1, w2) -> count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2));
在功能上等同于
new PriorityQueue<String>(new Comparator<String>() {
public int compare(String w1, String w2) {
return count.get(w1).equals(count.get(w2)) ? w2.compareTo(w1) : count.get(w1) - count.get(w2);
}
});
这也等同于创建一个单独的 class 来实现 Comparator<String>
,并将该 class 的一个实例作为参数传递给 PriorityQueue
。
至于将 Comparator
写成 if 语句,简短的回答是,不。比较器必须是 Comparator<String>
的实例。然而,也许同一个比较器的一个更容易理解的版本如下:
new PriorityQueue<String>((w1, w2) -> {
if (count.get(w1).equals(count.get(w2))) { // If the counts of w1 and w2 are the same,
return w2.compareTo(w1); // Then return the reverse lexicographical ordering of w1 and w2 (e.g. "Zebra" comes before "Apple")
} else if (count.get(w1) < count.get(w2)) {
return -1; // w1 comes before w2
} else {
return 1; // w1 comes after w2
}
});
注意:"Lexicographical ordering"本质上是按字母排序,但基于 ASCII 码。有关详细信息,请参阅 String#compareTo(String)
希望对您有所帮助!