优先级队列应用场景:Top K问题
PriorityQueue,即优先级队列,优先级队列作用是保证每次取出来的元素都是队列中最小的(Java优先级队列默认每次取最小元素)
PriorityQueue是Queue的实现类,而Queue接口是Collection接口的子接口,除了基本的Collection操作外,队列还提供了其他的插入,提取和检查的操作,每个方法存在两种形式:一种是抛出异常(操作失败时),另外一种情况返回一个特殊值(null或者false,取决于操作)。
特点:
1、优先级队列默认每次获取是队列中最小的,也可以通过comparator比较器类来自定义获取最大还是最小值
2、优先级队列中不能存储null
思路:
第一步:产生数据:ArrayList 存储产生的随机数
第二步:统计数据出现的次数:HashMap
key:出现的数据 value:数据出现的次数
第三步:统计出现最多的数据 TopK 优先级队列 ,给定容量为5的小根堆
注意:比较数据的次数,不能直接将Interger类型的数据作为优先级队列的数据类型,因为存储数据包含map中的键和值,优先级队列存放的是单个值。map是键值对类型—>Entry类型。在优先级队列中存放Entry类型的实体,比较value值
第一步、第二步中涉及到的代码在这篇文章中已经讲过https://blog.csdn.net/qq_49129184/article/details/123008470
第三步:
统计出现次数最多的5个数据 :
PriorityQueue <Map.Entry <Integer, Integer>> priorityQueue = new PriorityQueue <>(5, new Comparator <Map.Entry <Integer, Integer>>() {
@Override
public int compare(Map.Entry <Integer, Integer> o1, Map.Entry <Integer, Integer> o2) {
return o1.getValue() - o2.getValue();
}
});
遍历HashMap:
Iterator <Map.Entry <Integer, Integer>> iterator2 = hashMap.entrySet().iterator();
while (iterator2.hasNext()) {
Map.Entry <Integer, Integer> entry = iterator2.next();
if (priorityQueue.size() < 5) {
priorityQueue.add(entry);
} else {
//优先级队列中已经存在5个数据 ,小根堆,堆顶最小
Map.Entry <Integer, Integer> entry1 = priorityQueue.peek();
//比较出现次数
if (entry.getValue() > entry1.getValue()) {
//当前元素大于堆顶元素,删除堆顶,添加当前元素
priorityQueue.remove();
priorityQueue.add(entry);
}
}
}
打印数据:
Iterator<Map.Entry<Integer, Integer>> iterator1 = priorityQueue.iterator();
while (iterator1.hasNext()) {
Map.Entry<Integer, Integer> entry = iterator1.next();
System.out.println("数据:" + entry.getKey() + " 出现次数:" + entry.getValue());
}