1. 概述
本教程将探讨多种在Java数组中查找元素索引的方法,涵盖原生API和第三方库实现。这些技术在实际开发中常用于搜索、排序和数组修改等场景。
2. 使用for循环
最简单粗暴的方式就是用for
循环遍历数组:
核心思路:遍历数组时逐个检查元素,匹配则返回当前索引。遍历结束未找到则返回固定常量值(如-1
、Integer.MAX_VALUE
等)表示元素不存在。
int forLoop(int[] numbers, int target) {
for (int index = 0; index < numbers.length; index++) {
if (numbers[index] == target) {
return index;
}
}
return -1;
}
测试用例验证:
@Test
void givenIntegerArray_whenUseForLoop_thenWillGetElementIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(2, forLoop(numbers, 30));
}
@Test
void givenIntegerArray_whenUseForLoop_thenWillGetElementMinusOneIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-1, forLoop(numbers, 100));
}
✅ 优点:实现简单,适用于所有数组类型
❌ 缺点:时间复杂度O(n),大数据量时效率较低
3. 使用List的indexOf()
通过Arrays.asList()
将数组转为List后调用indexOf()
:
static int listIndexOf(Integer[] numbers, int target) {
List<Integer> list = Arrays.asList(numbers);
return list.indexOf(target);
}
⚠️ 注意:此方法仅适用于对象数组(如Integer[]
),不适用于基本类型数组(如int[]
)。
测试用例:
@Test
void givenIntegerArray_whenUseIndexOf_thenWillGetElementIndex() {
Integer[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(2, listIndexOf(numbers, 30));
}
@Test
void givenIntegerArray_whenUseIndexOf_thenWillGetElementMinusOneIndex() {
Integer[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-1, listIndexOf(numbers, 100));
}
✅ 优点:代码简洁
❌ 缺点:空间复杂度O(n)(因创建新List),且不适用基本类型数组
4. 使用Arrays的binarySearch()
利用二分查找算法高效定位索引:
@Test
void givenIntegerArray_whenUseBinarySearch_thenWillGetElementIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(2, Arrays.binarySearch(numbers, 30));
}
⚠️ 关键前提:数组必须已排序!未排序数组会导致不可预测结果。
未找到元素时的返回值规则:
@Test
void givenIntegerArray_whenUseBinarySearch_thenWillGetUpperBoundMinusIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-6, Arrays.binarySearch(numbers, 100)); // 目标值>最大值
}
@Test
void givenIntegerArray_whenUseBinarySearch_thenWillGetInArrayMinusIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-2, Arrays.binarySearch(numbers, 15)); // 目标值在数组范围内
}
@Test
void givenIntegerArray_whenUseBinarySearch_thenWillGetLowerBoundMinusIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-1, Arrays.binarySearch(numbers, -15)); // 目标值<最小值
}
返回值计算公式:(-(插入点) - 1)
,其中插入点是目标应插入的位置索引。
✅ 优点:时间复杂度O(log n),高效
❌ 缺点:要求数组有序,未排序数组需先排序(O(n log n))
5. 使用IntStream
Java 8+的函数式实现:
static int intStream(int[] numbers, int target) {
return IntStream.range(0, numbers.length)
.filter(i -> numbers[i] == target)
.findFirst()
.orElse(-1);
}
测试用例:
@Test
void givenIntegerArray_whenUseIntStream_thenWillGetElementIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(2, intStream(numbers, 30));
}
✅ 优点:代码简洁,函数式风格
❌ 缺点:性能略低于传统循环(流操作开销)
6. Apache Commons库
使用第三方库ArrayUtils.indexOf()
:
先添加Maven依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
基础用法:
@Test
void givenIntegerArray_whenUseApacheCommons_thenWillGetElementIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(2, ArrayUtils.indexOf(numbers, 30));
}
支持指定起始索引:
@Test
void givenIntegerArray_whenUseApacheCommonsStartingFromIndex_thenWillGetNegativeIndex() {
int[] numbers = { 10, 20, 30, 40, 50 };
assertEquals(-1, ArrayUtils.indexOf(numbers, 30, 3)); // 从索引3开始查找
}
✅ 优点:支持基本类型数组,功能灵活
❌ 缺点:需引入外部依赖
7. 性能对比
各方案复杂度分析:
方法 | 时间复杂度 | 空间复杂度 |
---|---|---|
for循环 | O(n) | O(1) |
List indexOf() | O(n) | O(n) |
Arrays binarySearch() | O(log n) | O(1) |
IntStream | O(n) | O(1) |
Apache Commons | O(n) | O(1) |
关键结论:
- 二分查找性能最优(O(log n)),但要求数组有序
- for循环和IntStream时间复杂度相同,但循环更高效
- List方案空间复杂度最高(因创建新List)
8. 总结
本文系统介绍了Java中查找数组元素索引的五种方案:
- for循环:最基础方案,适用于所有场景
- **List.indexOf()**:简洁方案,但仅限对象数组
- **Arrays.binarySearch()**:高效方案,要求数组有序
- IntStream:函数式方案,Java 8+推荐
- Apache Commons:功能丰富的第三方方案
实际开发中建议:
- ✅ 小数据量/无序数组 →
for循环
- ✅ 大数据量/已排序数组 →
binarySearch
- ✅ 需要功能扩展 →
Apache Commons
所有示例代码已上传至GitHub仓库,欢迎参考实践。