问题

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

自己写基于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. 场景题:假设有40亿QQ号,但只有1G内存,如何实现去重?

    当数据量比较大时,使用常规的方式来判重就不行了.例如,使用 MySQL 数据库判重,或使用 List.contains() 或 Set.contains() 判重就不行了,因为数据量太大会导致内存放不 ...

  2. jwt-shiro-springsecurity-oauth2对比

    1 实现token的方式概述 在cookie\session\token辨析一文已经知道了token这个概念,里面简单说明了token的组成就是数据+签名,给出了token实现身份验证的流程,并且详细 ...

  3. Golang-包8

    http://c.biancheng.net/golang/package/ Go语言包的基本概念 Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方 ...

  4. webrtc-streamer实时播放监控

    公司要做web端监控实时播放,经过调研,webrtc-streamer的方式对前后端项目侵入最少,且没有延迟卡钝的现象. 一.准备工作 一个摄像头,摄像头对应的rtsp流链接,一台电脑,一个vue项目 ...

  5. Linux glibc自带哈希表的用例及性能测试

    今天来看看Linux和一些常见的BSD系统上自带的hashmap. 是的,系统自带的.因为POSIX标准定义了一些常见的数据结构(比如哈希表.二叉搜索树.队列)和算法(比如二分查找和快速排序),这些接 ...

  6. oracle19.3打补丁

    补丁 36582781 - 数据库发布更新 19.24.0.0.240716 本文档在发布时准确无误.有关数据库版本更新 19.24.0.0.240716 的任何更改和其他信息,请参阅 My Orac ...

  7. FLink14--核心窗口--TumblingWindiwApp

    一.依赖 https://www.cnblogs.com/robots2/p/16048648.html 二. 代码 前言:window用作有keyBy情况,前面没有使用keyBy的话用windowA ...

  8. 清华博士后的DeepSeek使用手册,104页,真的是太厉害了!(免费领取源文件)

    <DeepSeek从入门到精通2025>是由清华大学元宇宙文化实验室的余梦珑博士后及其团队撰写.文档的核心内容围绕DeepSeek的技术特点.应用场景.使用方法以及如何通过提示语设计提升A ...

  9. 无分类无tag

    1 2 3

  10. Powershell 调用cmd 运行exe、bat、jar文件

    1. 配置路径 $nginxPath = "C:\path\to\nginx" $redisPath = "C:\path\to\redis" $ruoyiAd ...