杰瑞科技汇

Java数组如何实现contains功能?

总结概览

方法 优点 缺点 适用场景
循环遍历 最基础,无需任何额外知识或库 代码冗长,效率相对较低 学习基础,面试考点,简单脚本
Arrays.binarySearch() 效率极高 (O(log n)) 前提:数组必须已排序,否则结果错误 已排序的大型数组,追求极致性能
Arrays.asList().contains() 代码简洁,可读性好 有性能开销 (O(n)),会创建一个新列表对象 中小型数组,代码简洁性优先于性能
Java 8 Stream API 现代、函数式,代码简洁,可链式调用 有性能开销 (O(n)),对于简单场景可能略显复杂 现代Java项目,需要与其他流操作结合时
Apache Commons Lang 代码最简洁,经过高度优化 需要引入第三方库 已在项目中使用该库,或追求极致的代码简洁

方法1:使用 for 循环(最基础)

这是最原始、最直接的方法,不依赖任何 Java 库,适合初学者理解底层逻辑。

Java数组如何实现contains功能?-图1
(图片来源网络,侵删)

原理:手动遍历数组中的每一个元素,如果找到与目标值相等的元素,就立即返回 true,如果遍历完整个数组都没有找到,就返回 false

import java.util.Arrays;
public class ArrayContainsExample {
    public static boolean containsUsingLoop(int[] array, int valueToFind) {
        // 处理 null 数组的情况
        if (array == null) {
            return false;
        }
        // 遍历数组
        for (int element : array) {
            if (element == valueToFind) {
                return true; // 找到即返回
            }
        }
        return false; // 循环结束未找到
    }
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        int target = 3;
        if (containsUsingLoop(numbers, target)) {
            System.out.println("数组中包含 " + target);
        } else {
            System.out.println("数组中不包含 " + target);
        }
        // 测试不包含的情况
        int notFound = 6;
        if (!containsUsingLoop(numbers, notFound)) {
            System.out.println("数组中不包含 " + notFound);
        }
    }
}
  • 优点:直观,无任何依赖。
  • 缺点:代码量多,不如其他方法简洁。

方法2:使用 Arrays.binarySearch()(最高效,但有前提)

如果你确定数组是有序的(从小到大或从大到小),这是最快的方法。

原理:使用二分查找算法,其时间复杂度为 O(log n),远快于线性查找的 O(n)。

⚠️ 重要:如果数组未排序,binarySearch 的行为是未定义的,它可能返回错误的结果,比如返回一个负数表示“未找到”,但这不代表该值真的不在数组中。

Java数组如何实现contains功能?-图2
(图片来源网络,侵删)
import java.util.Arrays;
public class BinarySearchExample {
    public static void main(String[] args) {
        // 数组必须是有序的!
        int[] sortedNumbers = {1, 3, 5, 7, 9};
        int target = 5;
        // 使用 binarySearch
        // 如果找到,返回元素的索引(>= 0)
        // 如果未找到,返回 (-(插入点) - 1)(一个负数)
        int result = Arrays.binarySearch(sortedNumbers, target);
        if (result >= 0) {
            System.out.println("数组中包含 " + target + ",索引在: " + result);
        } else {
            System.out.println("数组中不包含 " + target);
        }
        // 错误示例:对未排序的数组使用 binarySearch
        int[] unsortedNumbers = {9, 1, 5, 3, 7};
        int wrongResult = Arrays.binarySearch(unsortedNumbers, 5);
        System.out.println("对未排序数组查找5的结果是: " + wrongResult); // 可能是 -6 或其他意想不到的值
    }
}
  • 优点:在数组已排序的情况下,查找速度极快。
  • 缺点仅适用于已排序的数组,如果数组未排序,必须先排序(排序本身是 O(n log n) 的开销),这可能会让该方法失去优势。

方法3:使用 Arrays.asList().contains()(最常用)

这是最简洁、最通用的方法,适用于任何类型的数组(包括基本类型和对象类型)。

原理Arrays.asList() 将数组转换为一个固定大小的 List 视图,然后调用 List 接口自带的 contains() 方法。

import java.util.Arrays;
public class AsListContainsExample {
    public static void main(String[] args) {
        // 对基本类型数组
        int[] numbers = {1, 2, 3, 4, 5};
        int target = 3;
        // 注意:Arrays.asList(numbers) 会创建一个包含数组本身作为唯一元素的 List
        // List<int[]> 而不是 List<Integer>
        // 所以对于基本类型数组,需要先转换为对象数组
        boolean contains = Arrays.stream(numbers).boxed().collect(Collectors.toList()).contains(target);
        System.out.println("基本类型数组是否包含 " + target + ": " + contains);
        // 更好的方式是直接使用 Stream (见方法4)
        // 或者,对于对象数组,这个方法非常直接
        String[] names = {"Alice", "Bob", "Charlie"};
        String nameToFind = "Bob";
        // 对于对象数组,直接使用即可
        boolean nameContains = Arrays.asList(names).contains(nameToFind);
        System.out.println("字符串数组是否包含 " + nameToFind + ": " + nameContains);
    }
}
  • 优点:代码非常简洁,可读性高,适用于对象数组。
  • 缺点
    1. 对于基本类型数组(如 int[]),不能直接使用,需要先转换(使用 Stream API 会更方便)。
    2. Arrays.asList() 会创建一个新的 ArrayList 对象(尽管是视图),对于非常大的数组可能会有轻微的性能开销。
    3. contains() 方法本身仍然是线性查找,时间复杂度为 O(n)。

方法4:使用 Java 8 Stream API(现代推荐)

这是 Java 8 引入的现代函数式方法,代码优雅且功能强大。

原理:将数组转换为流,然后使用 anyMatch() 方法检查是否存在至少一个元素满足给定的条件。

Java数组如何实现contains功能?-图3
(图片来源网络,侵删)
import java.util.Arrays;
public class StreamContainsExample {
    public static void main(String[] args) {
        // 对基本类型数组
        int[] numbers = {1, 2, 3, 4, 5};
        int target = 3;
        // 使用 Stream API
        boolean containsInt = Arrays.stream(numbers).anyMatch(num -> num == target);
        System.out.println("基本类型数组是否包含 " + target + ": " + containsInt);
        // 对对象数组
        String[] names = {"Alice", "Bob", "Charlie"};
        String nameToFind = "Bob";
        boolean containsString = Arrays.stream(names).anyMatch(name -> name.equals(nameToFind));
        System.out.println("字符串数组是否包含 " + nameToFind + ": " + containsString);
        // 可以使用方法引用简化代码
        boolean containsStringRef = Arrays.stream(names).anyMatch("Bob"::equals);
        System.out.println("使用方法引用是否包含 Bob: " + containsStringRef);
    }
}
  • 优点
    • 代码简洁、现代。
    • 统一地处理基本类型和对象类型的数组。
    • 可与 Stream 的其他操作(如 filter, map, collect)无缝链式调用,功能强大。
  • 缺点
    • 对于这种简单的“包含”检查,相比传统的 for 循环,可能会有微小的性能开销(但通常可以忽略不计)。
    • 需要理解 Java 8 Stream 的基本概念。

方法5:使用 Apache Commons Lang(第三方库)

如果你的项目中已经使用了 Apache Commons Lang 库,这是最简单、最可靠的选择。

原理ArrayUtils 工具类提供了 contains() 静态方法。

你需要添加依赖 (Maven):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version> <!-- 使用最新版本 -->
</dependency>

代码示例

import org.apache.commons.lang3.ArrayUtils;
public class ApacheCommonsExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        int target = 3;
        if (ArrayUtils.contains(numbers, target)) {
            System.out.println("数组中包含 " + target);
        }
        String[] names = {"Alice", "Bob", "Charlie"};
        String nameToFind = "David";
        if (!ArrayUtils.contains(names, nameToFind)) {
            System.out.println("数组中不包含 " + nameToFind);
        }
    }
}
  • 优点:代码最简洁,可读性极高,库本身经过高度优化。
  • 缺点:需要引入第三方依赖。

如何选择?

  • 如果你是初学者或在学习基础:使用 for 循环,理解其原理。
  • 如果你的数组是已排序的且性能至关重要:使用 Arrays.binarySearch()
  • 如果你在写简单的代码,且追求简洁(特别是对象数组):使用 Arrays.asList().contains()
  • 如果你在编写现代 Java (8+) 代码Stream API 是非常好的选择,因为它功能全面且符合现代编程风格。
  • 如果你的项目已经依赖了 Apache Commons Lang:直接使用 ArrayUtils.contains(),这是最省事的方式。
分享:
扫描分享到社交APP
上一篇
下一篇