链地址法哈希表实现的Set使用自定义迭代器打印仅输出单元素问题排查
问题根因分析
所有问题都出在MySetIterator的实现逻辑上,部分问题涉及toString的细节处理,具体错误点如下:
- 迭代器初始化逻辑缺陷:构造器直接将
curNode赋值为table[0],既没有处理table[0]为空的场景,也没有预先找到第一个非空的桶,后续遍历会直接漏过所有前置空桶的元素。 hasNext()判断逻辑完全错误:当前仅判断curNode.next != null,只要当前链表遍历到尾节点,不管后面还有多少非空桶,都会直接返回false终止遍历,这就是你只能输出单个元素的核心原因。next()逻辑存在多处漏洞:- 每次取值直接取
curNode.next.element,永久漏掉当前节点本身存储的元素,每个链表的第一个元素永远不会被输出 - 没有处理
curNode为null的场景,遇到空桶会直接抛出空指针异常 - index自增时没有做边界判断,极易触发数组越界异常
- 每次取值直接取
toString输出格式存在冗余:最终输出会多一个尾部逗号,不符合集合的常规输出规范。
修复代码
修正后的迭代器实现
public class MySetIterator implements Iterator<Integer> { private Node curNode; int index; public MySetIterator() { index = 0; // 初始化时先找到第一个非空的桶 while (index < tableSize && table[index] == null) { index++; } curNode = index < tableSize ? table[index] : null; } public boolean hasNext() { // 当前节点非空就说明还有元素可以遍历 return curNode != null; } public Integer next() { if (!hasNext()) { throw new NoSuchElementException(); } // 先取当前节点的值 Integer res = curNode.element; // 移动到当前链表的下一个节点 curNode = curNode.next; // 如果当前链表遍历完了,找下一个非空桶 while (curNode == null && index < tableSize - 1) { index++; curNode = table[index]; } return res; } public void remove() { throw new UnsupportedOperationException(); } }
修正后的toString实现
public String toString() { if(numElements == 0) { return "{ }"; } StringBuilder string = new StringBuilder("{ "); MySetIterator iterator = new MySetIterator(); // 先加第一个元素,避免尾部冗余逗号 if (iterator.hasNext()) { string.append(iterator.next()); } while(iterator.hasNext()) { string.append(", ").append(iterator.next()); } string.append(" }"); return string.toString(); }
修复后可以正常输出所有存入的元素,也不会出现多余逗号、空指针等问题。
内容的提问来源于stack exchange,提问作者WeekendJedi
相关产品推荐
相关产品推荐

