Java中高效判断数组中是否包含某个元素的几种方法

目录
  • 检查数组是否包含某个值的方法
    • 使用List
    • 使用Set
    • 使用循环判断
    • 使用Arrays.binarySearch()
  • 时间复杂度
    • 使用一个长度为1k的数组
    • 使用一个长度为10k的数组
  • 总结
  • 补充
    • 使用ArrayUtils
    • 完整测试代码
    • 长字符串数据

如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作。同时,这个问题在Stack Overflow中也是一个非常热门的问题。在投票比较高的几个答案中给出了几种不同的方法,但是他们的时间复杂度也是各不相同的。本文将分析几种常见用法及其时间成本。

检查数组是否包含某个值的方法

使用List

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

使用Set

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

使用循环判断

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

使用Arrays.binarySearch()

Arrays.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。这种方法得到的结果可能并不精确,但是是最简单清晰的方式。

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

使用一个长度为1k的数组

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

使用一个长度为10k的数组

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

总结

显然,使用一个简单的循环方法比使用任何集合都更加高效。许多开发人员为了方便,都使用第一种方法,但是他的效率也相对较低。因为将数组压入Collection类型中,首先要将数组元素遍历一遍,然后再使用集合类做其他操作。

如果使用Arrays.binarySearch()方法,数组必须是已排序的。由于上面的数组并没有进行排序,所以该方法不可使用。

实际上,如果你需要借助数组或者集合类高效地检查数组中是否包含特定值,一个已排序的列表或树可以做到时间复杂度为O(log(n)),hashset可以达到O(1)。

(英文原文结束,以下是译者注)

补充

使用ArrayUtils

除了以上几种以外,Apache Commons类库中还提供了一个ArrayUtils类,可以使用其contains方法判断数组和值的关系。

import org.apache.commons.lang3.ArrayUtils;
public static boolean useArrayUtils(String[] arr, String targetValue) {
    return ArrayUtils.contains(arr,targetValue);
}

同样使用以上几种长度的数组进行测试,得出的结果是该方法的效率介于使用集合和使用循环判断之间(有的时候结果甚至比使用循环要理想)。

useList: 323
useSet: 3028
useLoop: 141
useArrayBinary: 12
useArrayUtils: 181
-------
useList: 3703
useSet: 35183
useLoop: 3218
useArrayBinary: 14
useArrayUtils: 3125

其实,如果查看ArrayUtils.contains的源码可以发现,他判断一个元素是否包含在数组中其实也是使用循环判断的方式。

部分代码如下:

 if(array == null) {
        return -1;
    } else {
        if(startIndex < 0) {
            startIndex = 0;
        }

        int i;
        if(objectToFind == null) {
            for(i = startIndex; i < array.length; ++i) {
                if(array[i] == null) {
                    return i;
                }
            }
        } else if(array.getClass().getComponentType().isInstance(objectToFind)) {
            for(i = startIndex; i < array.length; ++i) {
                if(objectToFind.equals(array[i])) {
                    return i;
                }
            }
        }

        return -1;
    }

所以,相比较之下,我更倾向于使用ArrayUtils工具类来进行一些合数祖相关的操作。毕竟他可以让我少写很多代码(因为自己写代码难免有Bug,毕竟apache提供的开源工具类库都是经过无数开发者考验过的),而且,效率上也并不低太多。

完整测试代码

显然,使用一个简单的循环方法比使用任何集合都更加高效。许多开发人员为了方便,都使用第一种方法,但是他的效率也相对较低。因为将数组压入Collection类型中,首先要将数组元素遍历一遍,然后再使用集合类做其他操作。

package zaLearnpackage;
import org.apache.commons.lang3.ArrayUtils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
//检查数组是否包含某个值的方法
public class TestArray {
    //使用List
public static boolean useList(String[] arr,String targetValue){
    return Arrays.asList(arr).contains(targetValue);
}
//使用Set
public static boolean useSet(String[] arr,String targetValue){
    Set<String> set=new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);
}
//使用循环判断
public static boolean useLoop(String[] arr,String targetValue){
    for(String s:arr){
        if(s.equals(targetValue))
            return true;
        }
        return false;
    }
//查找有序数组中是否包含某个值的用法
public static boolean useArraysBinarySearch(String[] arr,String targetValue){
    int a=Arrays.binarySearch(arr, targetValue);
    if(a>0)
        return true;
    else
        return false;
}
//使用ArrayUtils
public static boolean useArrayUtils(String[] arr,String targetValue){
    return ArrayUtils.contains(arr,targetValue);
}
public static void main(String[] args) {
    String[] arr=new String[]{"CD","BC","EF","DE","AB","JK"};
    //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
        long startTime2=System.nanoTime();
        for(int i=0;i<100000;i++){
            useSet(arr, "A");
        }
        long endTime2=System.nanoTime();
        long duration2=endTime2-startTime2;
        System.out.println("useSet:"+duration/1000000);
        //use loop
        long startTime3=System.nanoTime();
        for(int i=0;i<100000;i++){
            useLoop(arr, "A");
        }
        long endTime3=System.nanoTime();
        long duration3=endTime3-startTime3;
        System.out.println("useLoop:"+duration/1000000);
        //use Arrays.binarySearch()
        long startTime4=System.nanoTime();
        for(int i=0;i<100000;i++){
            useArraysBinarySearch(arr, "A");
        }
        long endTime4=System.nanoTime();
        long duration4=endTime4-startTime4;
        System.out.println("useArraysBinarySearch:"+duration/1000000);
}
}
/*
 * 显然,使用一个简单的循环方法比使用任何集合都更加高效。许多开发人员为了方便,都使用第一种方法,但是他的效率也相对较低。因为将数组压入Collection类型中,首先要将数组元素遍历一遍,然后再使用集合类做其他操作。
 */

长字符串数据

遇到一些有规律的长字符串数据的解决办法(找到是否存在要查找的元素,非遍历)

String inputStrs = "北京,天津,上海,四川,湖南,广州,深圳,海南";
String[] strList = inputStrs.split(",");

String target = "上海";//1
String result = Arrays.asList(strList).contains(target) ? "查到咯!" : "没这个城市啊...";
//2Set<String> set = new HashSet<>(Arrays.asList(strList));
System.out.println(set.contains(target)); // true
System.out.println(result); // result="查到咯!"-----------

到此这篇关于Java中高效判断数组中是否包含某个元素的几种方法的文章就介绍到这了,更多相关Java包含某个元素判断内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java基础之不简单的数组

    目录 引言 数组也是一种类型 数组特点 数组的声明和初始化 1.静态初始化 2.动态初始化 数组和内存 总结 引言 相信有过编程基础的小伙伴都知道数组这个数据结构,它应该也是我们第一个接触的数据结构,学过C或者C++的应该知道数组和指针紧密相关,那么在java里没有了指针,java里的数组又有哪些不同的特点呢?下面就来介绍一下java里的数组: 数组也是一种类型 数组里面的数组元素都是唯一的,这个大家应该都知道,但是因为java是面向对象语言,类与类之间又有继承关系(C++中同样拥有),所以有时

  • Java 数组迭代你会用吗

    目录 1.概述 2.通过循环进行数组迭代 3.JDK 8 之前使用老方式进行数组迭代 4.使用 Java 8 Stream 进行数组迭代 5.字符串的应用 6.总结 Java 数组是我们学习或工作中常用到的数据结构,我们会经常写数组迭代的代码,但你的代码是最优雅的么? 本文介绍三种数组迭代的方式以及最佳实践. 1.概述 首先我们通过遍历数组值的基本方法,来迭代数组.其次我们用 Java 比较古老的方法实现,最后我们再使用 Java 8 的 Stream API 将数组转成迭代器. 除此之外,我们

  • java学习之一维数组中重复元素的去除

    目录 一.基本思路 二.步骤 1.设置判断数组Arr[ ] 2.继承数组newArr[ ]获取不重复元素 总结 一.基本思路 首先,假设一个一维数组arr[ ]={ 4, 3, 35, 3, 2, 4, 6, 3},其中有三个重复元素 3,4,3.要如何剔除呢,由于还没有涉猎到一些经典的调用,所以我选择了用新的数组newArr[ ]去继承原来数组中的不重复的元素,另外还需要一个判断数组Arr[ ],来判断arr[ ]中哪几个元素是重复的,才好去除掉. 二.步骤 1.设置判断数组Arr[ ] 代码

  • Java关于数组的介绍与使用

    目录 一.前言 二.数组的定义 数组定义的形式: 格式1: 格式2: 三.数组的初始化方式: 1.动态初始化 动态开辟的示意图: 2.静态初始化 四.索引访问数组 五.数组长度表示 六.遍历数组 方法一: 实例演示: 代码: 方法二: 实例演示: 代码: 七.数组的初始值 实例演示: 代码: 一.前言 前面我们学习了随机数的介绍和使用,那么这篇我们来学习java中数组的定义和使用, java的数组和c语言的十分类似. 二.数组的定义 数组定义的形式: 格式1: 数据类型 [ ] 数组名 :如in

  • java循环结构、数组的使用小结

    数组 数组是是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理. 数组本身是引用数据类型,既可以存储基本数据类型,也可以存储引用数据类型.它的元素相当于类的成员变量. 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址. 数组的长度一旦确定,就不能修改. 通过下标(或索引)的方式调用指定位置的元素. 数组的分类: 按照维度:一维数组.二维数组.三维数组.-按照元素的数据类型分:基本数据类型元素的数组.引用数据类型元素

  • Java中高效判断数组中是否包含某个元素的几种方法

    目录 检查数组是否包含某个值的方法 使用List 使用Set 使用循环判断 使用Arrays.binarySearch() 时间复杂度 使用一个长度为1k的数组 使用一个长度为10k的数组 总结 补充 使用ArrayUtils 完整测试代码 长字符串数据 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种不同的方法,但是他们的时间复杂度也是各不相同

  • vue如何判断数组中的对象是否包含某个值

    目录 判断数组中的对象是否包含某个值 判断对象是否包含某个属性,el-table formatter判断 1.表格部分 2.方法体部分 判断数组中的对象是否包含某个值 xxx (array, str) { var index = array.findIndex(item => item.id=== str) // var index = array.indexOf(str) // 当数组里的对象为字符串时用这个方法更简单 return index // -1 说明array中不存在id为str的

  • php判断数组中是否存在指定键(key)的方法

    本文实例讲述了php判断数组中是否存在指定键(key)的方法.分享给大家供大家参考.具体分析如下: php中有两个函数用来判断数组中是否包含指定的键,分别是array_key_exists和isset array_key_exists语法如下 array_key_exists($key, $array) 如果键存在返回true isset函数语法如下 isset($array[$key]) 如果键存在返回true 演示代码如下: <?php $array = array("Zero&quo

  • 利用JS十分钟判断数组中存在元素的多种方式

    前言 在前端开发中,经常会遇到要判断数组中是否存在某个元素.其实判断的方式有很多种,我们一个一个来了解下. 我们先来定义一个数组: const arr = [ 13, false, 'abcd', undefined, 13, null, NaN, [1, 2], { a: 123 }, () => Date.now(), new Date('2021/03/04'), new RegExp('abc', 'ig'), Symbol('sym'), ]; 在这个数组中,我们包含了好几种类型:nu

  • Java编程实现统计数组中各元素出现次数的方法

    本文实例讲述了Java编程实现统计数组中各元素出现次数的方法.分享给大家供大家参考,具体如下: package javatest; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class NumOfEle { public static void main(String[] ar

  • java实现向有序数组中插入一个元素实例

    整理文档,搜刮出一个java实现向有序数组中插入一个元素,稍微整理精简一下做下分享 package cn.jbit.array; import java.util.*; public class Insert { public static void main(String[] args) { //字符排序 char[] chars = new char[9]; chars[0] = 'a'; chars[1] = 'c'; chars[2] = 'u'; chars[3] = 'b'; cha

  • java获取两个数组中不同数据的方法

    本文实例讲述了java获取两个数组中不同数据的方法.分享给大家供大家参考.具体实现方法如下: public static <T> List<T> compare(T[] t1, T[] t2) { List<T> list1 = Arrays.asList(t1); List<T> list2 = new ArrayList<T>(); for (T t : t2) { if (!list1.contains(t)) { list2.add(t)

  • java使用Hashtable过滤数组中重复值的方法

    本文实例讲述了java使用Hashtable过滤数组中重复值的方法.分享给大家供大家参考,具体如下: package org.eline.core.web.support; import java.util.Hashtable; /***************************** * * @author zdw * */ public class ObjectFilter { public static void main(String[] args) { // String 测试 S

  • Java实现删除排序数组中重复元素的方法小结【三种方法比较】

    本文实例讲述了Java实现删除排序数组中重复元素的方法.分享给大家供大家参考,具体如下: 题目描述: 给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度. 不要使用额外的数组空间,必须在原地没有额外空间的条件下完成. 一:通过ArrayList解决 时间复杂度和空间复杂度都为O(n) ArrayList<Integer> list = new ArrayList<Integer>(); // 去掉数组中重复的元素 public int r

随机推荐