问题

可比较泛型怎么新建数组?

自己写基于AVL树的散列表时,在自动扩容的时候需要遍历AVL树的Key,所以需要AVL树提供一个方法返回一个Key数组以遍历,初始实现如下:

     /**
* 用于辅助遍历Key
*/
class KeyQueue {
private K[] queue; private int size; public KeyQueue(int capacity) {
queue = (K[]) new Object[capacity];
size = 0;
} public void enQueue(K key) {
queue[size] = key;
size++;
} public Object[] getQueue() {
return queue;
}
} /**
* 返回所有键
*
* @return 键数组
*/
public Object[] getKeyArray() {
KeyQueue queue = new KeyQueue(size);
preOrder(root, queue);
return queue.getQueue();
} private void preOrder(Node node, KeyQueue queue) {
if (node == null) {
return;
}
queue.enQueue(node.key);
preOrder(node.left, queue);
preOrder(node.right, queue);
}

KeyQueue 类是用于辅助装载Key的,因为自带的数组你不知道它装多少了,所以在此基础上简单封装了一个size变量。

但是这样会报错:

"C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\jbr\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\lib\idea_rt.jar=13543:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Project\DataStructureJavaLearn2021\out\production\data_structure_java top.minuy.structure.hash.Test
Test AVLTreeHashTable :
Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Comparable; ([Ljava.lang.Object; and [Ljava.lang.Comparable; are in module java.base of loader 'bootstrap')
at top.minuy.structure.map.AVLTreeMap$KeyQueue.<init>(AVLTreeMap.java:59)
at top.minuy.structure.map.AVLTreeMap.getKeyArray(AVLTreeMap.java:79)
at top.minuy.structure.hash.AVLTreeHashTable.resize(AVLTreeHashTable.java:214)
at top.minuy.structure.hash.AVLTreeHashTable.add(AVLTreeHashTable.java:92)
at top.minuy.structure.hash.AVLTreeHashTable.add(AVLTreeHashTable.java:10)
at top.minuy.structure.hash.Test.testHashTable(Test.java:61)
at top.minuy.structure.hash.Test.main(Test.java:21) Process finished with exit code 1

然后到网上看看有没有可以new一个可比较对象数组,发现好像并没有。

只能放弃这个想法。

解决

后来想了下,数组其实也是一种类,还不知道哪里有关于可比较泛型数组这方面的内容介绍,个人猜测转不了的原因应该是它们两个数组类Object[] 和 K[] 没有继承关系,但是想了下,它们里面的元素有继承关系。所以应该是在元素级别强转,而不是数组级别。

所以AVLTreeMap中的改为:

    /**
* 用于辅助遍历Key
*/
class KeyQueue {
private Object[] queue; private int size; public KeyQueue(int capacity) {
queue = new Object[capacity];
size = 0;
} public void enQueue(Object key) {
queue[size] = key;
size++;
} public Object[] getQueue() {
return queue;
}
} /**
* 返回所有键
*
* @return 键数组
*/
public Object[] getKeyArray() {
KeyQueue queue = new KeyQueue(size);
preOrder(root, queue);
return queue.getQueue();
} private void preOrder(Node node, KeyQueue queue) {
if (node == null) {
return;
}
queue.enQueue(node.key);
preOrder(node.left, queue);
preOrder(node.right, queue);
}

就返回Object数组

但是AVLTreeHashTable这边因为类型原因报错了

    /**
* 重新分配散列表大小
*
* @param capacity 新的散列表大小
*/
private void resize(int capacity) {
// System.out.println("resize : " + capacity + " size : " + size); AVLTreeMap<K, V>[] newTable;
newTable = new AVLTreeMap[capacity];
for (int i = 0; i < newTable.length; i++) {
newTable[i] = new AVLTreeMap<>();
} K[] keyArray;
for (int i = 0; i < table.length; i++) {
AVLTreeMap<K, V> map = table[i];
keyArray = (K[])map.getKeyArray();
for (int j = 0; j < keyArray.length; j++) {
// System.out.println("["+j+"]"+keyArray[j] + " ");
int hash = getHash(keyArray[j]);
newTable[hash].add(keyArray[j], map.get(keyArray[j]));
}
// System.out.println();
// System.out.println("index : " + i);
} table = newTable;
}

这句:

keyArray = (K[])map.getKeyArray();

也是一样的错误,我们应该从数组中取出元素后再强转。

所以修改为:

    /**
* 重新分配散列表大小
*
* @param capacity 新的散列表大小
*/
private void resize(int capacity) {
// System.out.println("resize : " + capacity + " size : " + size); AVLTreeMap<K, V>[] newTable;
newTable = new AVLTreeMap[capacity];
for (int i = 0; i < newTable.length; i++) {
newTable[i] = new AVLTreeMap<>();
} Object[] keyArray;
for (int i = 0; i < table.length; i++) {
AVLTreeMap<K, V> map = table[i];
keyArray = map.getKeyArray();
for (int j = 0; j < keyArray.length; j++) {
// System.out.println("["+j+"]"+keyArray[j] + " ");
K key = (K) keyArray[j];
int hash = getHash(key);
newTable[hash].add(key, map.get(key));
}
// System.out.println();
// System.out.println("index : " + i);
} table = newTable;
}

其中这句:

K key = (K) keyArray[j];

就是在元素从数组中取出后才强转,因为运行时它原本就是AVLTreeMap那边返回的K类型的元素,所以可以强转成功~

至此,问题解决~~

【Java】可比较泛型建数组传递报强转类型错误解决方案的更多相关文章

  1. 【java】泛型的作用是在编译阶段防止错误输入,绕过编译就绕过泛型,可用反射验证

    package com.tn.collect; import java.lang.reflect.Method; import java.util.ArrayList; public class Fa ...

  2. jmeter发送json数据,报405、400错误解决方案

    1.405错误解决方案:添加HTTP信息头管理器(错误因数:发送格式未设置) 2.400错误解决方案:json文本格式有误(注意:换行.空格等)解决方案:对照json文本数据(错误因数:发送的json ...

  3. Java基础 - 泛型详解

    2022-03-24 09:55:06 @GhostFace 泛型 什么是泛型? 来自博客 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了&quo ...

  4. 跟着刚哥梳理java知识点——泛型(十三)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...

  5. Java“禁止”泛型数组

    Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...

  6. Java 泛型 五:泛型与数组

    简介 上一篇文章介绍了泛型的基本用法以及类型擦除的问题,现在来看看泛型和数组的关系.数组相比于Java 类库中的容器类是比较特殊的,主要体现在三个方面: 数组创建后大小便固定,但效率更高 数组能追踪它 ...

  7. Java泛型与数组深入研究

    Java中的泛型与数组平时开发用的很多,除了偶尔遇到"NullPointerException"和"IndexOutOfBoundsException"一般也不 ...

  8. 《徐徐道来话Java》(2):泛型和数组,以及Java是如何实现泛型的

    数组和泛型容器有什么区别 要区分数组和泛型容器的功能,这里先要理解三个概念:协变性(covariance).逆变性(contravariance)和无关性(invariant). 若类A是类B的子类, ...

  9. Java层与Jni层的数组传递(转)

    源:Java层与Jni层的数组传递 Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的S ...

  10. Android开发实践:Java层与Jni层的数组传递

    转载:http://www.linuxidc.com/Linux/2014-03/97561.htm Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是 ...

随机推荐

  1. 新一代python版本与依赖管理工具 uv

    uv python版本与依赖管理 选择原因 1. 新的好玩.rust开发的执行速度快 2. 确实方便 3. 轻,软件就十几二十兆,占磁盘小 4. uv.lock可以锁版本 场景应用 场景一 从 ana ...

  2. CDS标准视图:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE

    视图名称:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE 视图类型: 视图代码: 点击查看代码 @AbapCatalog.compiler.compareFilter: tru ...

  3. CDS标准视图:优先级描述数据 I_GenericPriorityTextData

    视图名称:优先级描述数据 I_GenericPriorityTextData 视图类型:基础视图 视图代码: 点击查看代码 @AbapCatalog.sqlViewName: 'IGENPRIOTEX ...

  4. winform 引用AForge调用摄像头拍照

    Nuget安装这个2个: AForge.Controls; AForge.Video.DirectShow; code: namespace WindowsFormsApp1 { partial cl ...

  5. Java8新特性时间日期库

    Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...

  6. Event Store-其它存储

    背景 ENode是一个CQRS+Event Sourcing架构的开发框架,Event Sourcing需要持久化事件,事件可以持久化在DB,但是DB由于面向的是CRUD场景,是针对数据会不断修改或删 ...

  7. w3cschool-Hibernate 教程

    什么是 ORM? ORM 表示 Object-Relational Mapping (ORM),是一个方便在关系数据库和类似于 Java, C# 等面向对象的编程语言中转换数据的技术.一个 ORM 系 ...

  8. 第三届全国高校计算机能力挑战赛-C

    单项选择题 1.题 (3.0分) 以下叙述正确的是().  A.在C程序,至少要包含一个库函数  B.C程序的一行可以写多条语句  C.对一个C程序进行编译就可以生成可执行文件  D.C程序中的注释只 ...

  9. 平滑升级mariadb

    问题 Centos7自带的MariaDB版本是5.5 ,版本过于老旧,现想升级到最新版本,且数据不丢失 措施 备份原来的数据 mysqldump -u root -p --all-databases ...

  10. ABC224

    ABC224 D 题目大意 有一个九个点的无向图棋盘,上面有八个棋子,一次操作能将一个棋子沿边移到空点上,问将每个棋子移到与它编号相同的点最少几步. 解题思路 考虑使用 BFS. 用 string 存 ...