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

如何检测一个数组(未排序)是否包含一个指定的值?这在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)。

时间: 2024-12-28 08:52:42

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

js数组合并(一个数组添加到另一个数组里面)方法

js定义两个数组. var arrA=[1,2,3]; var arrB=[4,5,6]; 要实现[1,2,3,4,5,6],如果直接arrA.push(arrB); 则arrB只会作为了arrA的一个元素.执行如图: 要合并或连接,则需要使用concat() 方法. concat(Array) 方法 concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.array1.concat([item1[, item2[, . . . [, itemN

位运算解决“一个数组中,只有一个数字出现n次,其他数字出现k次”问题

转自:https://blog.csdn.net/monster_girl/article/details/52928864 在学习完位操作后,经常会遇到一类关于查找缺失整数的问题. 第一类是给你一个数组,告诉你这些数字的范围是什么,然后让你查找这个缺失的数字(例如无序数组的范围是从1到10,不重复的9个数). 这类问题的解决方法比较多样,第一种,因为给定了范围可以通过计算数字总和值,然后分别减去这些数字,剩下的则是缺失的数字.第二种,对这个数组进行排序,遍历整个数组,然后判断相邻的元素是否连续

java中如何判断一个字符串是否包含另外一个字符串的方法

indexOf(String s)的使用,如果包含,返回的值是包含该子字符串在父类字符串中起始位置:如果不包含必定全部返回值为-1 package my_automation; public class z_test { public static void main(String[] args) { String test = "This is test for string"; System.out.println(test.indexOf("This"));

C# 判断一个数组是否包含某个给定的元素

string[] elements = new string[50];             if ( Array.IndexOf<string>( elements, "sss" ) != -1 )             {                 //存在                 //返回的值就是 "sss" 在数组中的下标             }             else             {         

Javascript 中 检查一个数组是否包含某对象

function contains(a, obj) { for (var i = 0; i < a.length; i++) { if (a[i] === obj) { return true; } } return false; } 一个朴素的方法 大部分浏览器有  array.indexOf() 或者 array.includes() 方法 CoffeeScript 和 Dart 的方法

哈希(3) - 判断一个数组是否为另一个数组的子集

给定两个数组:arr1[0..m-1]和arr2[0..n-1]. 判断arr2[]是否为arr1[]的子集.这两个数组都是无序的. 例如: 输入: arr1[] = {11, 1, 13, 21, 3, 7}, arr2[] = {11, 3, 7, 1} 输出: arr2是arr1的子集. 输入: arr1[] = {1, 2, 3, 4, 5, 6}, arr2[] = {1, 2, 4} 输出: arr2是arr1的子集. 输入: arr1[] = {10, 5, 2, 23, 19},

php如何判断一个字符串是否包含另一个字符串

来自1:http://blog.sina.com.cn/s/blog_8edc37a801016yha.html -------------------------------------------------------------------- 我觉得最简单的就是:(用这种最好,StrPos效率最高) strpos($a, $b) !== false 如果$a 中存在 $b,则为 true ,否则为 false. 用 !== false (或者 === false) 的原因是如果 $b 正

哈希(3) - 推断一个数组是否为还有一个数组的子集

给定两个数组:arr1[0..m-1]和arr2[0..n-1]. 推断arr2[]是否为arr1[]的子集. 这两个数组都是无序的. 比如: 输入: arr1[] = {11, 1, 13, 21, 3, 7}, arr2[] = {11, 3, 7, 1} 输出: arr2是arr1的子集. 输入: arr1[] = {1, 2, 3, 4, 5, 6}, arr2[] = {1, 2, 4} 输出: arr2是arr1的子集. 输入: arr1[] = {10, 5, 2, 23, 19}

C语言中函数中传入一个数组,并且返回一个数组

一.C语言可以很容易将一个数组传递给一个自定义函数,格式如下:main(){ adb(float a[],int n);}float adb(float a[],int n){ …… return ^ ;}二.下面是C语言如何将一个数组从自定义函数返回 1.一维数组 #include<stdio.h> int *arry ( int a[]); int main () { int a[]={0,1,0,1,1,0,1,0}; int *b =arry(a) ;        int i; fo