泛型数组二分查找返回前两索引或栈溢出异常问题求助
泛型二分查找(带Comparator)实现方案
嘿,我之前也折腾过这个需求,非泛型的二分查找确实简单,但泛型+Comparator的组合要注意几个关键点,尤其是解耦比较逻辑和保证数组有序性!下面给你一套完整的实现思路和代码,应该能解决你的问题:
核心思路
泛型版本的关键在于不依赖元素自身的Comparable接口,而是通过传入Comparator来定义比较规则,这样就能支持任意类型(包括那些没实现Comparable的自定义类),同时完美兼容Integer、Double、String这些常见类型。另外一定要记住:二分查找的前提是数组已经按照Comparator的规则排好序,否则查找结果会完全错误!
完整代码实现
1. 泛型二分查找工具方法
import java.util.Comparator; import java.util.Scanner; public class GenericBinarySearch { // 泛型二分查找方法,支持任意类型,依赖Comparator完成比较逻辑 public static <E> int binarySearch(E[] array, E target, Comparator<? super E> comparator) { // 边界检查:避免空指针异常 if (array == null || comparator == null) { throw new IllegalArgumentException("数组或比较器不能为null"); } if (target == null) { throw new IllegalArgumentException("目标元素不能为null"); } int low = 0; int high = array.length - 1; while (low <= high) { // 用这种方式计算mid,避免low+high过大导致整数溢出 int mid = low + (high - low) / 2; int compareResult = comparator.compare(array[mid], target); if (compareResult == 0) { return mid; // 找到目标元素,返回索引 } else if (compareResult < 0) { low = mid + 1; // 目标在右半区间,调整左边界 } else { high = mid - 1; // 目标在左半区间,调整右边界 } } return -1; // 遍历完未找到目标,返回-1 }
2. 用户交互与测试逻辑
接着写主方法,实现你想要的「用户选择类型→生成数组→执行查找」流程:
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 提示用户选择查找类型 System.out.println("请选择要查找的数组类型:"); System.out.println("1. Integer数组"); System.out.println("2. Double数组"); System.out.println("3. String数组"); int choice = scanner.nextInt(); scanner.nextLine(); // 清除输入缓冲区的换行符 switch (choice) { case 1: // 生成预排序的Integer数组 Integer[] intArray = {1, 3, 5, 7, 9, 11, 13, 15}; System.out.print("请输入要查找的整数:"); int targetInt = scanner.nextInt(); int intResult = binarySearch(intArray, targetInt, Integer::compare); printResult(intResult, targetInt); break; case 2: // 生成预排序的Double数组 Double[] doubleArray = {1.2, 3.4, 5.6, 7.8, 9.0, 11.2}; System.out.print("请输入要查找的小数:"); double targetDouble = scanner.nextDouble(); int doubleResult = binarySearch(doubleArray, targetDouble, Double::compare); printResult(doubleResult, targetDouble); break; case 3: // 生成预排序的String数组(按字典序) String[] stringArray = {"apple", "banana", "cherry", "date", "elderberry"}; System.out.print("请输入要查找的字符串:"); String targetString = scanner.nextLine(); // 用忽略大小写的比较器,提升用户体验 int stringResult = binarySearch(stringArray, targetString, String::compareToIgnoreCase); printResult(stringResult, targetString); break; default: System.out.println("无效的选择,请重新运行程序!"); } scanner.close(); } // 统一的结果打印方法,复用逻辑 private static <E> void printResult(int index, E target) { if (index != -1) { System.out.printf("找到元素 %s,索引为 %d%n", target, index); } else { System.out.printf("未找到元素 %s%n", target); } } }
关键细节说明
- 泛型通配符:用
Comparator<? super E>而非Comparator<E>,这样可以接受更宽泛的比较器(比如元素父类的Comparator),提升代码灵活性。 - 溢出防护:计算mid时用
low + (high - low)/2,避免low+high数值过大时超出int类型范围导致溢出。 - 健壮性处理:加入了null值判断,避免运行时空指针异常,让代码更稳定。
- 简化写法:调用时用
Integer::compare、String::compareToIgnoreCase这类方法引用,替代繁琐的匿名内部类,代码更简洁易读。
常见问题排查
如果你当前的实现「勉强可用但有问题」,大概率是这几个原因:
- 数组未按Comparator规则排序:比如String数组用了忽略大小写的比较器,但数组本身是按大小写敏感排序的,会直接导致查找失败。
- 未处理null值:比如目标元素或数组为null时没有做校验,运行时会抛出异常。
- 泛型类型不兼容:传入的Comparator类型和数组元素类型不匹配,编译时可能有警告,运行时会出错。
内容的提问来源于stack exchange,提问作者Mark Louprette Jr
相关产品推荐
相关产品推荐

