Java运行LinearProbingHashSet报ArithmeticException: / by zero如何解决
报错根本原因
你遇到的ArithmeticException: / by zero是hash方法中% a.length运算导致的,数组a的长度为0,根源是LinearProbingHashSet的带参构造函数存在变量赋值错误:
你在带参构造public LinearProbingHashSet(int m)中,错误将静态变量capacity的值赋值给了参数m,而非将参数值赋值给类成员变量。capacity初始默认值为0,因此你传入的10完全没生效,最终a = (Key[]) new Object[m]创建了长度为0的数组,取模运算自然触发除零错误。
同时代码还存在多个关联逻辑缺陷会导致后续运行异常:
- 构造函数没有正确处理成员变量和参数的同名问题,未加
this关键字区分 loadFactor、maxLoadFactor未初始化,默认值为0会导致扩容逻辑异常- 默认无参构造没有初始化数组
a和成员变量m insert方法逻辑顺序错误:先计算哈希再检查扩容,扩容后数组长度变化,之前计算的哈希值会失效,还可能触发数组越界- 成员变量
capacity被定义为static,会被所有实例共享,不符合哈希表的设计逻辑
修复方案
1. 修正LinearProbingHashSet的成员变量定义和构造函数逻辑
删掉冗余的静态capacity变量,正确初始化负载因子,构造函数正确赋值成员变量:
public class LinearProbingHashSet <Key>{ private int n; private int m; private Key[] a; private double maxLoadFactor; public LinearProbingHashSet(int capacity){ this.m = capacity; n= 0; a = (Key[]) new Object[m]; maxLoadFactor = 0.5; // 对应你原有扩容阈值n >= m/2 } public LinearProbingHashSet(){ this(4); // 直接调用带参构造,默认容量4 } // 其余原有get方法、hash方法保留不变
2. 修正insert方法的执行顺序
先检查扩容,再计算哈希插入,避免扩容后哈希值失效:
void insert(Key key) { // 先检查是否需要扩容 if (n >= m * maxLoadFactor) resize(2*m); int hashValue = hash(key); for (int i = hashValue; a[i] != null; i = (i + 1) % m) { if (a[i].equals(key)) { return; } } a[i] = key; n++; }
3. 修正resize方法的内部逻辑
避免嵌套调用构造函数的逻辑冲突,直接新建数组重哈希:
public void resize(int newCapacity) { Key[] temp = (Key[]) new Object[newCapacity]; for (int i = 0; i < m; i++) { if (a[i] != null) { // 重新计算新数组的哈希位置 int hashVal = (a[i].hashCode() & 0x7fffffff) % newCapacity; while(temp[hashVal] != null) { hashVal = (hashVal + 1) % newCapacity; } temp[hashVal] = a[i]; } } a = temp; m = newCapacity; }
修复后即可解决除零报错,线性探测哈希表的插入、扩容逻辑也能正常运行。
内容的提问来源于stack exchange,提问作者Rand
相关产品推荐
相关产品推荐

