如何检查一个数组(未排序)中是否包含某个特定的值?在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

Java 高效检查一个数组中是否包含某个值的更多相关文章

  1. 在Java中如何高效的判断数组中是否包含某个元素

    原文出处: hollischuang(@Hollis_Chuang) 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Ove ...

  2. java中如何高效的判断数组中是否包含某个元素---

    package zaLearnpackage; import org.apache.commons.lang3.ArrayUtils; import java.util.Arrays; import ...

  3. 灵魂拷问:如何检查Java数组中是否包含某个值 ?

    在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题.比如说:如何检查Java数组中是否包含某个值 ?像这类灵魂拷问的主题,非常值得深入地研究一下. 另外,我想要告诉大家的是, ...

  4. js判断数组中是否包含某个值

    /** * 判断数组中是否包含某个值 * @param arr 数组 * @param str 值 * @returns {boolean} */ function contains(arr, str ...

  5. node js 判断数组中是否包含某个值

    判断数组中是否包含某个值这里有四种方法.用的测试数据: let arr=["a","b","c"]; let arr2={"a&q ...

  6. 七、如何在Java中高效检查一个数组是否含有一个值

    如何检查一个数组(非排序的)是否包含特定的值.这是个非常有用或经常被在Java中使用.这是个在Stack Overflow中高得票的问题.在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非 ...

  7. Java 正则判断一个字符串中是否包含中文

    使用正则判断一个字符串中是否包含中文或者中文字符 代码实现如下: import java.util.regex.Matcher; import java.util.regex.Pattern; /** ...

  8. Js 判断数组中是否包含某个值

    includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false. JavaScript Array includes() 方法

  9. 用JAVA写查询一个字符串中是否包含另外一个字符串以及出现的次数

    package JAVA; import java.awt.List;import java.util.ArrayList;/** *  * @author 梁小鱼 * */public class ...

随机推荐

  1. 去掉搜狗拼音烦人的x+;进入搜狗搜索

  2. MFC程序实现给对话框加入�背景图片

    1.插入一个Bitmap的资源图片,如果资源名称为:IDC_BITMAP1 2.在CXXXDialog::OnPaint()中实现: void CMyDialogDlg::OnPaint() { if ...

  3. show()与showDialog()的区别

    A.WinForm中窗体显示  显示窗体可以有以下2种方法:  Form.ShowDialog方法 (窗体显示为模式窗体) Form.Show方法 (窗体显示为无模式窗体) 2者具体区别如下: 1.在 ...

  4. WCF - 学习总目录

    WCF - 基础 WCF - 地址 WCF - 绑定 WCF - 绑定后续之自定义绑定 WCF - 契约 WCF - 序列化 WCF - 消息 WCF - 实例与会话 WCF - REST服务

  5. 从Swap函数谈加法溢出问题

    1.      初始题目 面试题:). 这个题目太经典,也太简单,有很多人都会不假思索结出答案: //Code 1 void Swap(int* a, int* b) { *a = *a + *b; ...

  6. Java基础知识强化之IO流笔记27:FileInputStream读取数据一次一个字节数组byte[ ]

    1. FileInputStream读取数据一次一个字节数组byte[ ]  使用FileInputStream一次读取一个字节数组: int read(byte[]  b) 返回值:返回值其实是实际 ...

  7. 卸载AMH 5.0面板的具体办法

    安装AMH 5.0面板只有YES.NO和EXIT,和AMH 4.X的安装.卸载.退出有点不同,那么如何卸载AMH 5.0面板呢? 1.root登录ssh 2.输入如下命令: killall php-f ...

  8. javascript中的call()和apply应用

    在javascript开发过程中,如果有看过几个javascirpt代码库,就会发现经常使用到call()和apply()函数,call()和aplly()结合javascript允许传递函数名,这种 ...

  9. Gym 100187B-A Lot of Joy

    题意:给一个字符串,将每个字符分开放进两个口袋,每次从两个口袋分别拿出一个字符,如果相同则开心,问开心的次数期望是多少. 分析:数学期望题,然而这是我最不拿手的...最后答案是每个字符在字符串出现的次 ...

  10. 删除mysql重复记录的办法

    网上有很多的办法,但是大多数都是通过临时表的办法,其实你是可以用一句简单的sql就可以做到: alter ignore table SOMETABLE add primary key(fields n ...