怎样高效判断数组中是否包含某个特定值

简介:

前言

怎样判断一个无序数组是否包含某个特定值呢?

这在JAVA中是一个非常实用的操作,在Stack Overflow问答网站中也同样是一个热门问题;

要完成这个判断,可以通过若干种不同的方式来实现,每种实现方式对应的时间复杂读有很大的不同;

接下来,我将展示四种不同的实现方式,以及这四种方式对应的时间开销。

四种不同方式来检查数组是否包含某个值

1、使用List:

    public static boolean useList(String[] arr, String targetValue) {
        return Arrays.asList(arr).contains(targetValue);
    }

2、使用Set:

    public static boolean useSet(String[] arr, String targetValue) {
        Set<String> set = new HashSet<String>(Arrays.asList(arr));
        return set.contains(targetValue);
    }

3、使用简单的循环语句:

复制代码
    public static boolean useLoop(String[] arr, String targetValue) {
        for (String s : arr) {
            if (s.equals(targetValue))
                return true;
        }
        return false;
    }
复制代码

4、使用Arrays.binarySearch()方法:

注:下面的代码是错误的,之所以列在下面是出于完整性考虑(四种判断方式),binarySearch()二分查找只能用于有序数组

运行下面程序,你有可能会得到异常结果;

复制代码
    public static boolean useArraysBinarySearch(String[] arr, String targetValue) {
        int a = Arrays.binarySearch(arr, targetValue);
        if (a > 0)
            return true;
        else
            return false;
    }
复制代码

四种实现方式对应的时间开销

以下代码可计算出以上四种实现方式大致的时间消耗,基本策略是使用不同大小的数组(5, 1k,10k)做测试,可能不是很精准,但这种方式很简单;

数组大小为5:

复制代码
public static void main(String[] args) {
        String[] arr = new String[] { "CD", "BC", "EF", "DE", "AB" };
        // use list
        long startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            useList(arr, "A");
        }
        long endTime = System.nanoTime();
        long duration = endTime - startTime;
        System.out.println("useList: " + duration / 1000000);
        // use set
        startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            useSet(arr, "A");
        }
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("useSet: " + duration / 1000000);
        // use loop
        startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            useLoop(arr, "A");
        }
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("useLoop: " + duration / 1000000);
        // use Arrays.binarySearch()
        startTime = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            useArraysBinarySearch(arr, "A");
        }
        endTime = System.nanoTime();
        duration = endTime - startTime;
        System.out.println("useArrayBinary: " + duration / 1000000);
    }
复制代码

运行结果:

useList: 13
useSet: 72
useLoop: 5
useArraysBinarySearch: 9

数组大小为1000:

        String[] arr = new String[1000];
        Random s = new Random();
        for (int i = 0; i < 1000; i++) {
            arr[i] = String.valueOf(s.nextInt());
        }

运行结果:

useList: 112
useSet: 2055
useLoop: 99
useArrayBinary: 12

数组大小为10000:

        String[] arr = new String[10000];
        Random s = new Random();
        for (int i = 0; i < 10000; i++) {
            arr[i] = String.valueOf(s.nextInt());
        }

运行结果:

useList: 1590
useSet: 23819
useLoop: 1526
useArrayBinary: 12

结论

从测试结果可以看出,使用简单的循环语句比使用任何集合都高效,很大一部分开发人员选择使用第一种方法(List),但这种方法其实是相对低效的。在使用集合提供的API前,需要把一个数组放到集合里,这需要消耗一定的时间,特别是对于Set集合;(注:其实ArrayList集合的性能跟普通的循环语句差不多,因为对于ArrayList,转换成集合的时候,仅仅是改变了内部的数组索引,遍历判断的时候,跟普通的循环语句类似);

如果要使用Arrays.binarySearch()方法,前提是数组要有序,在这个测试demo中,很显然数组是无序的,因此不该被使用;

事实上,如果你确实需要高效的去检查数组或集合中是否包含某个值,一个有序列表或者有序树能把时间复杂度降低到O(log(n)),或者使用散列集合,时间复杂度为O(1);


本文转自风一样的码农博客园博客,原文链接:http://www.cnblogs.com/chenpi/p/5484887.html,如需转载请自行联系原作者

相关文章
|
编译器 C++ Windows
【C++】vector问题解决(非法的间接寻址,迭代器失效 , memcpy拷贝问题)
不使用memcpy函数不就可以了,然后我们使用简单粗暴的赋值拷贝,这样就不会发生浅拷贝问题了!!!
292 1
基于蝗虫优化的KNN分类特征选择算法的matlab仿真
摘要: - 功能:使用蝗虫优化算法增强KNN分类器的特征选择,提高分类准确性 - 软件版本:MATLAB2022a - 核心算法:通过GOA选择KNN的最优特征以改善性能 - 算法原理: - KNN基于最近邻原则进行分类 - 特征选择能去除冗余,提高效率 - GOA模仿蝗虫行为寻找最佳特征子集,以最大化KNN的验证集准确率 - 运行流程:初始化、评估、更新,直到达到停止标准,输出最佳特征组合
|
存储 编解码 索引
了解FFmpeg音频通道布局结构:AVChannelLayout结构体解析
了解FFmpeg音频通道布局结构:AVChannelLayout结构体解析
547 1
|
机器学习/深度学习 算法 数据挖掘
掌握 Python 数字类型:从基础到高级应用的全面指南
掌握 Python 数字类型:从基础到高级应用的全面指南
162 0
|
存储 编译器 C语言
|
存储 缓存 算法
比Bloom Filter节省25%空间!Ribbon Filter在Lindorm中的应用
本文研究了一种新的过滤器Ribbon Filter,并将其集成到Lindorm中
45559 11
比Bloom Filter节省25%空间!Ribbon Filter在Lindorm中的应用
|
关系型数据库 MySQL
安装Mysql报错:mysql-community-server-5.7...my-) 需要:mysql-community解决
安装Mysql报错:mysql-community-server-5.7...my-) 需要:mysql-community解决
505 0
|
Java Shell Maven
Mac笔记本idea打包maven工程,本地环境运行正常,打包成功,却启动不成功
Mac笔记本idea打包maven工程,本地环境运行正常,打包成功,却启动不成功
326 0
|
NoSQL Redis 数据安全/隐私保护
Redis使用认证密码登录
Redis使用认证密码登录
|
JSON API 数据格式
八、.net core(.NET 6)配置读取appsettings文件内容的通用功能
添加通用读取配置文件功能在Wsk.Core.Package项目下,新增Microsoft.Extensions.Configuration包:
904 0
八、.net core(.NET 6)配置读取appsettings文件内容的通用功能