如何检查一个数组(未排序)中是否包含某个特定的值?在Java中,这是一个非常有用并又很常用的操作。同时,在StackOverflow中,有时一个得票非常高的问题。在得票比较高的几个回答中,时间复杂度差别也很大。

1、不同的实现方式

使用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);
}

使用循环

 public static boolean useLoop(String[] arr, String targetValue) {
for (String s : arr) {
if (s.equals(targetValue)) {
return true;
}
}
return false;
}

使用Arrays.binarySearch

  此法为二分搜索法,故查询前需要用sort()方法将数组排序,如果数组没有排序,则结果是不确定的,另外

  如果数组中含有多个指定值的元素,则无法保证找到的是哪一个。

 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个元素的情况下的不同表现。

5个

 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)的时间复杂度

转自http://www.diguage.com/archives/112.html

最新文章

  1. Android Paint的属性
  2. web基础----&gt;request的请求参数分析
  3. Android Volley框架的使用(1)
  4. C# 通过URL获取图片并显示在PictureBox上的方法
  5. VB最新使用教程
  6. 纯后台生成highcharts图片有哪些方法?
  7. bzoj1934: [Shoi2007]Vote 善意的投票
  8. 使用canvas制作在线画板
  9. 2.5.6 使用progressDialog创建进度对话框
  10. 闭包 this,arguemnts 问题
  11. C#截取字符串的方法小结
  12. 依赖注入和IOC
  13. FileSystemWatcher类监控文件的更改状态并且实时备份文件
  14. 安卓Acitivity的启动模式
  15. SharedPreferences实现保存用户名功能
  16. mysql日志分析工具之mysqlsla
  17. scipy 短时傅里叶变化
  18. foreach循环里不能remove/add元素的原理
  19. EBS CAS SSO测试
  20. mysql各数据类型的存储范围

热门文章

  1. Java - 推断元音辅音
  2. hdu 4773 Problem of Apollonius
  3. 去掉搜狗拼音烦人的x+;进入搜狗搜索
  4. UIwebView实现html的离线缓存
  5. Android自定义“图片+文字”控件四种实现方法之 二--------个人最推荐的一种
  6. android 59 LinearLayout 线性布局
  7. jackson 学习笔记
  8. php程序员的开始
  9. hadoop_并行写操作思路
  10. 深入理解shared pool共享池之library cache的library cache pin系列三