`

(转)在Java中如何高效的判断数组中是否包含某个元素

 
阅读更多
http://www.hollischuang.com/archives/1269
如何检查一个数组(无序)是否包含一个特定的值?这是一个在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提供的开源工具类库都是经过无数开发者考验过的),而且,效率上也并不低太多。
分享到:
评论

相关推荐

    在Java中如何高效的判断数组中是否包含某个元素Java开

    以上就是在Java中高效判断数组是否包含特定元素的一些关键知识点。根据实际需求和环境选择合适的方法,可以有效地提高代码的运行效率。在开发过程中,始终要关注性能优化,尤其是在处理大量数据时。

    Java中高效的判断数组中某个元素是否存在详解

    在Java编程中,判断一个无序数组是否包含特定元素是一项常见的任务。这篇文章主要探讨了四种不同的方法来实现这个功能,并分析了它们的时间复杂度。以下是这四种方法的详细解释: 1. 使用`List.contains()`: 这种...

    java判定数组或集合是否存在某个元素的实例

    Java编程语言提供了多种方法来判断数组或集合中是否存在特定的元素。这篇文章通过一个实例展示了如何在Java中实现这一功能。我们将详细讨论以下几种方法: 1. **数组中的元素判断**: - **方法1-1**: 使用`Arrays....

    java二维数组删除特定行代码

    在`delete`方法中,首先通过一个外层循环遍历`tongjidata`数组,检查每个元素是否满足删除条件。如果满足条件,则进入内层循环,再次遍历`data`数组,查找与当前`tongjidata`元素匹配的行。一旦找到,便执行删除操作...

    数据结构(JAVA)求一个含有n个整数元素的数组a0..n-1中的最大元素

    数组是一种线性数据结构,它包含相同类型的一组元素,这些元素在内存中是连续存储的,并可以通过索引访问。在Java中,数组可以通过声明数组变量并初始化来创建,例如`int[] array = new int[n];`其中`n`是数组的长度...

    jstl中判断list中是否包含某个值的简单方法

    为了优化性能,如果是在Java代码中进行操作,我们可以使用List的contains方法来高效地判断一个元素是否存在于List中。但在JSTL中,我们不能直接调用Java代码,因此必须采用JSTL标签实现。 以下是一个通用的模板,...

    Java数组十种操作方法-扣丁学堂.doc

    #### 四、检查数组是否包含某个元素 - **使用`contains`方法**:首先将数组转换为列表,然后使用`contains`方法来判断元素是否存在。 ```java boolean b = Arrays.asList(stringArray).contains("a"); System....

    判断以逗号分隔的字符串中是否包含某个数的实例

    本篇将详细探讨如何判断一个以逗号分隔的字符串是否包含某个特定的数,并提供一个Java实例作为参考。 首先,我们需要理解字符串的基本操作。在Java中,`String` 类型是不可变的,这意味着一旦创建了一个`String`...

    php在数组中查找指定值的方法

    如果你只需要确定数组是否包含某个值,而不需要知道具体的位置,则使用`in_array`函数会更加直接高效。 在实际的PHP编程过程中,灵活运用这两个函数可以帮助你处理很多关于数组查找的问题。例如,在数据库查询结果...

    java练习题--容器使用练习

    练习题可设计为实现双向遍历链表,插入和删除指定位置的元素,以及检查某个元素是否存在于链表中。 3. HashSet:HashSet是一个不包含重复元素的集合,不保证元素顺序,且不允许有null值。你可以编写练习题来练习...

    Java语言开发相关单词

    在Java中,数组是一种对象,拥有自己的类。数组的大小在创建时确定,并且不能改变。 ### 数组工具类:`Arrays` `Arrays`是Java中的一个工具类,提供了各种静态方法来操作数组,如排序、搜索等。这些方法简化了对数...

    90个高质量的java问答.pdf

    - **背景**:在 Java 编程中,经常需要判断一个数组中是否包含某个特定值。 - **方法**: - 使用 `Arrays.asList()` 方法将数组转换为列表,再调用 `contains()` 方法来查找元素是否存在。 - 对于基本数据类型的...

    布隆过滤器BloomFilters的一个简单Java库

    在Java开发中,特别是在处理大数据、内存限制或需要快速查询是否存在某个元素的场景下,布隆过滤器是一个非常实用的工具。`krisives-jbloomer-7afec7a`这个压缩包文件很可能包含了一个简单的Java实现的布隆过滤器库...

    java编写的集合版存储俄罗斯方块

    在Java中,一个方块可以由一个二维数组表示,每个元素代表方块的一个部分。为了实现360度旋转,我们需要设计一个旋转算法。基本思路是先将方块逆时针旋转90度,然后检查新位置是否超出屏幕边界或与已有方块重叠。...

    jdk数组的基础上的集合使用及详解.docx

    contains()检查是否包含某个元素;isEmpty()判断是否为空;forEach()用于迭代操作;indexOf()查找元素索引;iterator()获取迭代器;remove()删除指定位置的元素或对象;set()替换指定位置的元素;size()返回集合长度...

    Java集合概述与实例分析

    首先,Collection接口是所有单列集合的父接口,它定义了集合的基本操作,如添加元素(add),删除元素(remove)和判断是否包含某个元素(contains)等。Collection接口有两个重要的子接口:List和Set。 1. List接口:...

    Java集合框架总结

    - `boolean remove(Object o)`:移除集合中的某个元素。 - `int size()`:返回集合中元素的数量。 - `boolean isEmpty()`:检查集合是否为空。 - `boolean contains(Object o)`:判断集合中是否包含指定的元素。...

    java 笔试题

    // 辅助函数:判断数组中是否已存在某个元素 private static boolean contains(int[] array, int value) { for (int i = 0; i ; i++) { if (array[i] == value) { return true; } } return false; } } ``` ...

    java常用词汇汇总

    - **用途**:在编程中,定界符用于标识字符串、数组等数据结构的开始和结束位置。 #### Encapsulation [java] 封装 (hiding implementation details) - **中文释义**:封装 - **用途**:封装是面向对象编程的一个...

    2014年Java最全面试题以及答案.

    快速排序是通过选择一个“基准”元素,然后将数组分为两个子数组,一个包含小于基准的元素,另一个包含大于基准的元素,然后递归排序两个子数组。 8. Overload和Override的区别。Overloaded的方法是否可以改变...

Global site tag (gtag.js) - Google Analytics