如何编写适配任意数组类型的通用查找方法以避免代码重复?
嘿,完全懂你这种被重复代码纠缠的烦恼!每次写几乎一模一样的逻辑就只是换了个数组类型,既浪费时间又不好维护——当然有办法解决这个问题,下面给你几个实用的方案:
Java的泛型可以帮你写出适配任意引用类型的通用查找方法,不过要注意泛型不支持int、char这类基本类型,所以得用它们的包装类(Integer、Character)来定义数组。
先给你修正后的通用方法(顺便修复了你原代码里的小bug:原代码找到匹配后没终止循环,会返回最后一个匹配项的索引,而不是第一个):
import java.util.Objects; public class ArrayUtils { // 通用的查找第一个匹配项索引的方法 public static <T> int indexOf(T[] array, T target) { // 先处理数组为空的边界情况 if (array == null) { return -1; } for (int i = 0; i < array.length; i++) { // 用Objects.equals避免空指针异常(如果数组里有null元素也能处理) if (Objects.equals(array[i], target)) { return i; // 找到第一个匹配项就直接返回,不用继续循环 } } return -1; // 没找到返回-1 } }
使用的时候只需要把基本类型数组转成包装类数组(Java 5+支持自动装箱,使用起来很方便):
// 处理Integer数组 Integer[] intArray = {1, 3, 5, 7}; int intIndex = ArrayUtils.indexOf(intArray, 5); // 返回2 // 处理Character数组 Character[] charArray = {'a', 'b', 'c'}; int charIndex = ArrayUtils.indexOf(charArray, 'b'); // 返回1
如果你必须直接处理int[]、char[]这类基本类型数组,那没办法完全消除重载,但可以把核心逻辑尽量复用,或者直接利用Java标准库的工具类:
方式A:重载方法+复用逻辑
把循环判断的逻辑抽成一个通用的“模板”,不过因为基本类型无法用泛型,还是得写不同的重载方法,但至少减少重复代码:
public class PrimitiveArrayUtils { public static int indexOf(int[] array, int target) { return indexOfPrimitive(array, target); } public static int indexOf(char[] array, char target) { return indexOfPrimitive(array, target); } // 这里用反射实现通用逻辑(注意:反射会有性能损耗,不推荐在高频调用场景使用) private static <T> int indexOfPrimitive(T array, Object target) { try { int length = java.lang.reflect.Array.getLength(array); for (int i = 0; i < length; i++) { Object element = java.lang.reflect.Array.get(array, i); if (element.equals(target)) { return i; } } } catch (IllegalArgumentException e) { // 处理非数组类型的异常 e.printStackTrace(); } return -1; } }
方式B:直接用Java标准库
Java的java.util.Arrays类提供了针对基本类型数组的查找方法,但要注意Arrays.binarySearch()要求数组是已排序的,如果你的数组是无序的,这个方法不适用。如果是无序数组,还是得自己写重载方法,但可以参考方案1的思路修正原代码的bug。
如果你喜欢函数式编程的风格,也可以用Stream来实现通用查找:
import java.util.Objects; import java.util.stream.IntStream; public class StreamArrayUtils { public static <T> int indexOf(T[] array, T target) { return IntStream.range(0, array.length) .filter(i -> Objects.equals(array[i], target)) .findFirst() .orElse(-1); } }
最后再提醒你一下:你原代码里的循环没有在找到匹配项后终止,会遍历整个数组返回最后一个匹配的索引,这和你注释里“Find the first matched result”的需求不符,记得加上break或者直接返回哦!
内容的提问来源于stack exchange,提问作者Qichao Ying

