PriorityQueue 抛出类强制转换异常

Posted

技术标签:

【中文标题】PriorityQueue 抛出类强制转换异常【英文标题】:PriorityQueue throwing class cast exception 【发布时间】:2019-01-02 14:40:40 【问题描述】:

PriorityQueue add 方法在执行时抛出类转换异常(MyVertex 无法转换为 java.lang.Comparable)。

MyVertex 类型的一些 Object 插入正确,有些抛出异常,无法找到它们之间的差异。

见附在java中的代码行:

 PriorityQueue<Vertex> pq = new PriorityQueue<>();
 for (Edge edge : vertex.getEdges()) 
      pq.add(edge.getTo());
 

预期:pq.add() 方法不应抛出异常。

【问题讨论】:

MyVertex 实现 Comparable 了吗? 参见PriorityQueue.add():“抛出:ClassCastException - 如果指定的元素无法根据优先级队列的顺序与当前在此优先级队列中的元素进行比较” - 向我们展示您的MyVertex.compareTo-实现,似乎你那里有一个错误。 旁注:您忘记了new PriorityQueue&lt;&gt;(); 中的钻石——请不要使用原始类型。 @Hulk,第一个元素将被添加到PriorityQueue,即使它没有实现Comparable,因为没有其他元素可以比较。 @LiranSimanTov 请edit 你的问题包括一个minimal reproducible example 包括你的类,可以由其他人编译和测试,当你尝试向队列添加新条目时会引发异常. 【参考方案1】:

    实现Comparable 接口并在Vertex 类中覆盖ComapareTo 以满足优先级队列的排序。

    正如 java 文档所说 - add 如果指定的元素无法根据优先级队列的顺序与当前在此优先级队列中的元素进行比较,则抛出 ClassCastException

    正如您之前所说的那样,这是因为当 priorityQueues 的大小为 0(添加第一个元素时)时,add 调用不会抛出 ClassCastException。为了测试这一点,在调用 for 循环之前打印vertex.getEdges().size() 的大小。如果 size 看起来大于 0,那就是 ClassCastException 将被抛出。

当大小不为零时,将调用筛选操作,因为此处优先级队列中的底层数据结构是一个堆。

您看到的异常是从sift-up 触发的,因为内部筛选需要您的元素实现Comparable。并且sift-up在优先队列大小不为0时调用,或者添加了后续元素。

注意:

堆应该满足堆属性:如果P是C的父节点, 那么 P 的键(值)大于或等于(在 最大堆)或小于或等于(在最小堆中)C 的键。

sift-up:在树中向上移动一个节点,只要需要;习惯于 插入后恢复堆条件。称为“筛选”,因为节点 向上移动树,直到达到正确的水平,就像在筛子中一样。

Heap_data_structure

【讨论】:

以上是关于PriorityQueue 抛出类强制转换异常的主要内容,如果未能解决你的问题,请参考以下文章

ForEach 方法中的类强制转换异常

检索 HashMap 的迭代器会引发强制转换异常

Junit强制在方法调用上抛出异常

SSIS Conditional Split - 强制默认路径抛出异常

泛型和强制转换 - 不能将继承的类强制转换为基类

缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?