怎樣判斷Array(無序)中是否包含某個值呢?
阿新 • • 發佈:2019-01-02
問題
怎樣去判斷Array(無序)中是否包含某個值呢?
這是一個在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);
}
使用Loop
public static boolean useLoop(String[] arr, String targetValue) {
for (String s : arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
使用ArraysBinarySearch,這個方法只適用於已排序的Array
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的Array中進行查詢。這個方法可能不夠精確,但是這個思路還是很簡單清晰的。
注:測試環境為win7-64+JDK1.6
使用Array大小為5
public static void main(String[] args) {
System.out.println("---------array size is 5-----------");
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+" 毫秒");
}
結果:
---------array size is 5-----------
useList: 10 毫秒
useSet: 66 毫秒
useLoop: 4 毫秒
useArrayBinary: 4 毫秒
### 使用Array大小為1k
System.out.println("---------array size is 1k----------");
String[] arr = new String[1000];
Random s = new Random();
for (int i = 0; i < 1000; i++) {
arr[i] = String.valueOf(s.nextInt());
}
結果:
---------array size is 1k----------
useList: 762 毫秒
useSet: 7549 毫秒
useLoop: 677 毫秒
useArrayBinary: 14 毫秒
使用Array大小為10k
System.out.println("---------array size is 10k---------");
String[] arr = new String[10000];
Random s = new Random();
for (int i = 0; i < 10000; i++) {
arr[i] = String.valueOf(s.nextInt());
}
結果:
---------array size is 10k---------
useList: 7395 毫秒
useSet: 126341 毫秒
useLoop: 5776 毫秒
useArrayBinary: 17 毫秒
總結
從測試的結果可以清楚地知道,使用簡單的Loop比使用集合操作更加有效 。許多開發者使用List方式,但是那並不高效。把Array放到另一個Collection中需要讀取Array中的所有元素,這將花費不少的時間。
使用Arrays.binarySearch()的前提是這Array必須是有序的。
實際上,如果你真正需要高效地去判斷Array/Collection中是否包含某個值,一個排序了的List或者Tree的時間複雜度為O(log(n)),或者用HashSet,它的時間複雜度為O(1)。
翻譯:crane-yuan
[ 轉載請保留原文出處、譯者和譯文連結。]