您的位置:首页 > 编程语言 > Java开发

如何高效的检测一个数组是否包含某一个值

2015-01-09 20:53 417 查看
如何检测一个数组(未排序)是否包含一个指定的值?这在Java中是一个非常有用且常见的操作。这还是一个在stackoverflow投票最多的一个问题。在投票最多的答案中,有几种不同的方式来完成这个问题。但是时间复杂度存在很大的差异。下面,我将展示每个方法所花费的时间。

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


很明显:使用循环比使用集合效率要高。很多开发者使用第一种方法,但它是低效的。Pushing the array to another collection requires spin through all elements to read them in before doing anything with the collection type。
如果使用Arrays.binarySearch()方法,必须先对数组进行排序。在这例子中,数组并没有排序,所有不应该binarySearch()这个方法。
实际上,如果你确实需要检测一些数组/集合中是否包含某个值,你可以使用一个排序的列表或树,其时间复杂度为O(log(n))或者使用hashset,其时间复杂度为O(1)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 数组