Simple Java—Strings and Arrays(五)如何在java中有效率的检查一个数组中是否有某值?

Translate from Simple java

如何在java中有效率的检查一个数组中是否有某值?

如何检查一个数组(未排序)中是否含有一个确定的值?这是java中一个很有用并且经常使用到的操作。它同时是Stack Overflow网站上公投的第一名问题。根据这个问题的最佳回答,有如下几种不同的方式实现,这几种方式复杂度有很大的不同。接下来,我将来展示它们的时间花费。

1. 四种检查数组中值的方法


 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;
}


2. 时间复杂度


下面的代码会计算出四种方法近似的时间花费。最简单的办法是分别查询一个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


很明显,使用简单的循环比使用任何集合更有效率。许多开发者使用第一种方法,但实际上它效率并不高。在使用集合操作前,需要把数组中所有的元素都读入集合。

Arrays.binarySearch()方法被使用时,注意数组必须是已经排序好了的。前面的示例中,数组没有被排序,因此,这个方法不应该被使用。

事实上,如果你真的需要有效率的检查一个值是否存在与一个数组或是集合中。一个排好序(sort)的list或tree可以在O(log(n))时间复杂度做到。而hashset可以在O(1)的时间复杂度做的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值