在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题。比如说:如何检查Java数组中是否包含某个值 ?像这类灵魂拷问的主题,非常值得深入地研究一下。
另外,我想要告诉大家的是,作为程序员,我们千万不要轻视这些基础的知识点。因为基础的知识点是各种上层技术共同的基础,只有彻底地掌握了这些基础知识点,才能更好地理解程序的运行原理,做出更优化的产品。
我曾在某个技术论坛上分享过一篇非常基础的文章,结果遭到了无数的嘲讽:“这么水的文章不值得分享。”我点开他的头像进入他的主页,发现他从来没有分享过一篇文章,不过倒是在别人的博客下面留下过不少的足迹,大多数都是冷嘲热讽。我就纳闷了,技术人不都应该像我这样低调谦逊吗?怎么戾气这么重!
好了,让我们来步入正题。如何检查数组(未排序)中是否包含某个值 ?这是一个非常有用并且经常使用的操作。我想大家的脑海中应该已经浮现出来了几种解决方案,这些方案的时间复杂度可能大不相同。
我先来提供四种不同的方法,大家看看是否高效。
1)使用 List
public static boolean useList(String[] arr, String targetValue) {return Arrays.asList(arr).contains(targetValue);
}
Arrays 类中有一个内部类 ArrayList(可以通过 Arrays.asList(arr) 创建该实例),其 contains() 方法的源码如下所示。
public boolean contains(Object o) {return indexOf(o) != -1;
}
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
从上面的源码可以看得出,contains() 方法调用了 indexOf() 方法,如果返回 -1 则表示 ArrayList 中不包含指定的元素,否则就包含。其中 indexOf() 方法用来获取元素在 ArrayList 中的下标,如果元素为 null,则使用“==”操作符进行判断,否则使用 equals() 方法进行判断。
PS:关于“==”操作符和 equals() 方法,可以参照我另外一篇文章《如何比较 Java 的字符串?》
2)使用 Set
public static boolean useSet(String[] arr, String targetValue) {Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
HashSet 其实是通过 HashMap 实现的,当使用 new HashSet<String>(Arrays.asList(arr)) 创建并初始化了 HashSet 对象后,其实是在 HashMap 的键中放入了数组的值,只不过 HashMap 的值为默认的一个摆设对象。大家感兴趣的话,可以查看一下 HashSet 的源码。
我们来着重看一下 HashSet 的 contains() 方法的源码。
public boolean contains(Object o) {return map.containsKey(o);
}
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
从上面的源码可以看得出,contains() 方法调用了 HashMap 的 containsKey() 方法,如果指定的元素在 HashMap 的键中,则返回 true;否则返回 false。
3)使用一个简单的循环
public static boolean useLoop(String[] arr, String targetValue) {for (String s : arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
for-each 循环中使用了 equals() 方法进行判断——这段代码让我想起了几个词,分别是简约、高效、清晰。
4)使用 Arrays.binarySearch()
public static boolean useArraysBinarySearch(String[] arr, String targetValue) {int a = Arrays.binarySearch(arr, targetValue);
if (a > 0)
return true;
else
return false;
}
不过,binarySearch() 只适合查找已经排序过的数组。