七、如何在Java中高效检查一个数组是否含有一个值

如何检查一个数组(非排序的)是否包含特定的值。这是个非常有用或经常被在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。这种处理也许是不精确的,但是很清晰也很简单。

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()方法被使用。

在这种情况下,由于数组是没有排序的,所以它不能使用。

实际上,如果你真的需要去高效查找一个值是否在一个数组或集合中,一个排序的list或tree 可以在O(log(n))或hashset 可以在O(1)完成。

原文地址:https://www.cnblogs.com/seaspring/p/5268369.html