Java数组经for循环填充后全为null且触发ArrayIndexOutOfBoundsException问题
问题原因分析与解决方案
咱们一步步拆解你遇到的核心问题,然后逐个解决:
1. 数组越界异常(ArrayIndexOutOfBoundsException: 69903)的根源
- 你初始化的数组长度是
69903,数组的合法索引范围是0到69902(数组索引从0开始计数)。 - 你的循环条件只判断了
scanner.hasNextLine(),如果wordlist.txt里的单词数量超过69903个,当循环变量i增长到69903时,执行words[i] = input就会触发越界异常——因为69903已经超出了数组的最大合法索引。 - 另外,你调用二分查找时传入的
hi参数是words.length(也就是69903),虽然这个值本身不会直接越界,但结合数组未排序、可能存在null元素的情况,会让查找逻辑出现额外问题。
2. 循环后数组“全为null”的真相
你说循环内打印input和words[i]都正常,那数组前i个元素肯定是有值的。出现“全为null”的情况,大概率是:
- 数组越界异常提前终止了程序,你还没来得及查看数组的正常内容,就被异常信息打断了;
- 或者你后续遍历数组时用了错误的范围(比如写成
i <= words.length),触发了越界异常,误以为数组全为null。
具体修复方案
方案一:用动态列表彻底避免数组越界
固定长度数组很容易因为文件行数变化出问题,改用ArrayList<String>存储单词,它会自动扩容,完全解决越界风险:
// 替换原来的数组初始化和循环代码 List<String> wordList = new ArrayList<>(); while(scanner.hasNextLine()) { String input = scanner.nextLine(); wordList.add(input); } // 转换成数组(如果需要保持原有的数组参数) String[] words = wordList.toArray(new String[0]);
方案二:如果坚持用固定数组,添加索引判断
如果你一定要用固定长度数组,先确认wordlist.txt的准确行数,然后在循环中加入索引上限判断:
for(int i = 0; scanner.hasNextLine() && i < words.length; i++) { String input = scanner.nextLine(); words[i] = input; }
这样当索引达到数组长度时就会停止循环,避免越界。
修复二分查找的核心问题
你的代码里打印了"Done sorting input words",但完全没有执行排序操作!二分查找必须在已排序的数组上进行,否则结果完全不可靠。添加排序代码:
Arrays.sort(words); // 如果用ArrayList,就用Collections.sort(wordList)
另外,二分查找的hi参数应该传入words.length - 1(数组最后一个元素的索引),同时修复递归边界避免死循环:
// 调用search时修改hi参数 if(search(key, words, 0, words.length - 1) < 0) { // ... } // 修复后的search方法 public static int search(String key, String[] arr, int lo, int hi) { if(hi < lo) { return -1; } int mid = lo + (hi - lo) / 2; int compute = arr[mid].compareTo(key); if (compute > 0) { return search(key, arr, lo, mid - 1); // 改为mid-1,避免死循环 } else if (compute < 0) { return search(key, arr, mid + 1, hi); } else { return mid; } }
完整修复后的代码
import java.util.Scanner; import java.util.Arrays; import java.io.File; import java.util.ArrayList; import java.util.List; public class BinarySearch { public static void main(String[] args) throws Exception { File file = new File("wordlist.txt"); Scanner scanner = new Scanner(file); List<String> wordList = new ArrayList<>(); while(scanner.hasNextLine()) { String input = scanner.nextLine(); wordList.add(input); } scanner.close(); // 记得关闭IO资源,避免内存泄漏 String[] words = wordList.toArray(new String[0]); System.out.println("Done reading input words"); Arrays.sort(words); System.out.println("Done sorting input words"); Scanner query = new Scanner(System.in); System.out.print("请输入要搜索的单词:"); String key = query.nextLine(); query.close(); if(search(key, words, 0, words.length - 1) < 0) { System.out.println(key + " 不在英语词典中。"); } else { System.out.println(key + " 是英语词典的一部分。"); } } public static int search(String key, String[] arr, int lo, int hi) { if(hi < lo) { return -1; } int mid = lo + (hi - lo) / 2; int compute = arr[mid].compareTo(key); if (compute > 0) { return search(key, arr, lo, mid - 1); } else if (compute < 0) { return search(key, arr, mid + 1, hi); } else { return mid; } } }
内容的提问来源于stack exchange,提问作者gamerage3
相关产品推荐
相关产品推荐

