1. 程式人生 > >如何高效檢查一個數組中是否包含某個值?

如何高效檢查一個數組中是否包含某個值?

轉載地址:http://www.diguage.com/archives/112.html

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
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:  12
useSet:  65
useLoop:  2
useArrayBinary:  7

使用大一點的陣列(1k個元素):

int length = 1000;
String[] arr = new String[length];

Random s = new Random();
for (int i = 0; i < length; i++) {
    arr[i] = String.valueOf(s.nextInt());
}
結果:
useList:  115
useSet:  2010
useLoop:  97
useArrayBinary:  9
使用更大一點的元素(10k個元素):
int length = 10000;
String[] arr = new String[length];

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

結果:

useList:  1678
useSet:  25609
useLoop:  1802
useArrayBinary:  10
從上面的結果可以清晰看到,使用簡單迴圈的相比使用其他集合操作更高效。很多很多開發人員使用第一種方法,但是它並不是最高效的。將陣列轉化成其他的任何集合型別都需要先將所有元素讀取到集合類中,才能對這個集合型別做其他的事情。

當使用Arrays.binarySearch()方法時,陣列必須是排好序的。如果陣列不是排好序的,則不能使用這個方法。

事實上,如果你真的需要高效地檢查一個數組或者集合中是否包含一個值,一個排好序的陣列或者樹可以達到O(log(n))的時間複雜度,HashSet甚至能達到O(1)的時間複雜度。