在Java中如何高效的判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作。同时,这个问题在Stack Overflow中也是一个非常热门的问题。在投票比较高的几个答案中给出了几种不同的方法,但是他们的时间复杂度也是各不相同的。本文将分析几种常见用法及其时间成本。
检查数组是否包含某个值的方法
使用List
|
1
2
3
|
public static boolean useList(String[] arr, String targetValue) { return Arrays.asList(arr).contains(targetValue);} |
使用Set
|
1
2
3
4
|
public static boolean useSet(String[] arr, String targetValue) { Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue);} |
使用循环判断
|
1
2
3
4
5
6
7
|
public static boolean useLoop(String[] arr, String targetValue) { for(String s: arr){ if(s.equals(targetValue)) return true; } return false;} |
使用Arrays.binarySearch()
Arrays.binarySearch()方法只能用于有序数组!!!如果数组无序的话得到的结果就会很奇怪。
查找有序数组中是否包含某个值的用法如下:
|
1
2
3
4
5
6
7
|
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。这种方法得到的结果可能并不精确,但是是最简单清晰的方式。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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);} |
运行结果:
|
1
2
3
4
|
useList: 13useSet: 72useLoop: 5useArraysBinarySearch: 9 |
使用一个长度为1k的数组
|
1
2
3
4
5
6
|
String[] arr = new String[1000];Random s = new Random();for(int i=0; i< 1000; i++){ arr[i] = String.valueOf(s.nextInt());} |
结果:
|
1
2
3
4
|
useList: 112useSet: 2055useLoop: 99useArrayBinary: 12 |
使用一个长度为10k的数组
|
1
2
3
4
5
6
|
String[] arr = new String[10000];Random s = new Random();for(int i=0; i< 10000; i++){ arr[i] = String.valueOf(s.nextInt());} |
结果:
|
1
2
3
4
|
useList: 1590useSet: 23819useLoop: 1526useArrayBinary: 12 |
总结
显然,使用一个简单的循环方法比使用任何集合都更加高效。许多开发人员为了方便,都使用第一种方法,但是他的效率也相对较低。因为将数组压入Collection类型中,首先要将数组元素遍历一遍,然后再使用集合类做其他操作。
如果使用Arrays.binarySearch()方法,数组必须是已排序的。由于上面的数组并没有进行排序,所以该方法不可使用。
实际上,如果你需要借助数组或者集合类高效地检查数组中是否包含特定值,一个已排序的列表或树可以做到时间复杂度为O(log(n)),hashset可以达到O(1)。
(英文原文结束,以下是译者注)
使用ArrayUtils
除了以上几种以外,Apache Commons类库中还提供了一个ArrayUtils类,可以使用其contains方法判断数组和值的关系。
|
1
2
3
4
|
import org.apache.commons.lang3.ArrayUtils;public static boolean useArrayUtils(String[] arr, String targetValue) { return ArrayUtils.contains(arr,targetValue);} |
同样使用以上几种长度的数组进行测试,得出的结果是该方法的效率介于使用集合和使用循环判断之间(有的时候结果甚至比使用循环要理想)。
|
1
2
3
4
5
6
7
8
9
10
11
|
useList: 323useSet: 3028useLoop: 141useArrayBinary: 12useArrayUtils: 181-------useList: 3703useSet: 35183useLoop: 3218useArrayBinary: 14useArrayUtils: 3125 |
其实,如果查看ArrayUtils.contains的源码可以发现,他判断一个元素是否包含在数组中其实也是使用循环判断的方式。
部分代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
if(array == null) { return -1; } else { if(startIndex < 0) { startIndex = 0; } int i; if(objectToFind == null) { for(i = startIndex; i < array.length; ++i) { if(array[i] == null) { return i; } } } else if(array.getClass().getComponentType().isInstance(objectToFind)) { for(i = startIndex; i < array.length; ++i) { if(objectToFind.equals(array[i])) { return i; } } } return -1; } |
所以,相比较之下,我更倾向于使用ArrayUtils工具类来进行一些合数祖相关的操作。毕竟他可以让我少写很多代码(因为自己写代码难免有Bug,毕竟apache提供的开源工具类库都是经过无数开发者考验过的),而且,效率上也并不低太多。
在Java中如何高效的判断数组中是否包含某个元素的更多相关文章
- java中如何高效的判断数组中是否包含某个元素---
package zaLearnpackage; import org.apache.commons.lang3.ArrayUtils; import java.util.Arrays; import ...
- 在Java中怎样高效的推断数组中是否包括某个元素
来自 http://www.hollischuang.com/archives/1269? 怎样检查一个数组(无序)是否包括一个特定的值?这是一个在Java中经经常使用到的并且非常实用的操作.同一时候 ...
- Jquery判断数组中是否包含某个元素$.inArray()的用法
判断数组里面是否包含某个元素可以使用 $.inArray("元素(字符串)",数组名称) 进行判断 ,当存在该元素(字符串)时,返回该元素在数组的下标,不存在时返回 -1 示例代码 ...
- 161101、在Java中如何高效判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...
- 在Java中如何高效判断数组中是否包含某个元素
如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种 ...
- 《剑指Offer》第1题(Java实现):在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
一.题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...
- JS判断数组中是否有重复元素的方法
判断数组中是否有重复元素,最容易想到的方法是使用2重循环,逐个遍历,比较,但是这个是最慢,最笨的方法,百度得出了更好的方法. var ary = new Array("111",& ...
- js 判断数组中是否存在
/* 判断数组中是否存在 var somearray = ["mon", "tue", "wed", "thur"] s ...
- 面试题:给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字
题目:给定一个长度为N的数组,其中每个元素的取值范围都是1到N.判断数组中是否有重复的数字.(原数组不必保留) 方法1.对数组进行排序(快速,堆),然后比较相邻的元素是否相同.时间复杂度为O(nlog ...
随机推荐
- GGS-DDU HDU - 4966
GGS-DDU Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total S ...
- 【XSY2111】Chef and Churus 分块 树状数组
题目描述 有一个长度为\(n\)的数组\(A\)和\(n\)个区间\([l_i,r_i]\),有\(q\)次操作: \(1~x~y\):把\(a_x\)改成\(y\) \(2~x~y\):求第\(l\ ...
- Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2) A - D2
A. Be Positive 链接:http://codeforces.com/contest/1130/problem/A 题意: 给一段序列,这段序列每个数都除一个d(−1e3≤d≤1e3)除完后 ...
- Annihilate(SA)
题目描述 黑暗之主的蜈蚣几乎可以毁灭一切,因此小正方形陷入了苦战…… 小正方形现在需要减弱黑暗之主的攻击. 一个黑暗之主的攻击可以用一个仅有小写字母的字符串表示. 现在黑暗之主向小正方形发动了若干攻击 ...
- Dos 批处理 Shutdown
第一步: win + R,打开"运行" 第二步: 输入cmd 第三步: 输入color a或color b改成自己喜欢的颜色 第四步: 在shutdown后面输入不同的命令达到不同 ...
- A1006. Sign In and Sign Out
At the beginning of every day, the first person who signs in the computer room will unlock the door, ...
- c# WebApi之身份验证:Basic基础认证
为什么需要身份认证 身份认证是为了提高接口访问的安全性,如果没有身份验证,那么任何匿名用户只要知道服务器的url,就可以随意访问服务器,从而访问或者操作数据库,这会是很恐怖的事. 什么是Basic基础 ...
- 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,nloglogutil
封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,代码比较简单,主要是把MongoTarget的配置.FileTarget的配置集成到类中,同时利用缓存依赖来判断是否需要重新创 ...
- 收藏:win32 控件之 sysLink控件(超链接)
来源:https://blog.csdn.net/dai_jing/article/details/8683487 手动创建syslink(msdn): CreateWindowEx(, WC_LIN ...
- 第三十四篇-Palette(调色板)的使用
由于屏幕录制图片转换关系,不甚清晰,还是附上效果图 可以看出,上面文字和背景颜色确实会根据图片的变化而变化. 里面有3个组件,toolbar,textview,imageview,其中textview ...