Java 判斷陣列是否包含某個值
阿新 • • 發佈:2018-11-23
參照連結:http://www.hollischuang.com/archives/1269
查詢效率對比表:
陣列容量 | 查詢次數 | List | Set | Loop | BinarySearch | ArrayUtils |
6 | 10 | 331390 | 38718 | 14571 | 34738(有序) | 13755 |
6 | 100000 | 42319492 | 204266488 | 7266007 | 11627486(有序) | 3777349 |
10 | 10 | 397205 | 926739 | 22571 | 無 | 17764 |
10000 | 10 | 7949871 | 42562837 | 3443155 | 無 | 53373 |
10000 | 10 | 4645222 | 50564550 | 4626643 | 99976(有序) | 55648 |
BinarySearch(查詢陣列必須有序): 原始碼使用二分查詢實現元素查詢
private static int binarySearch0(Object[] a, int fromIndex, int toIndex, Object key) { int low = fromIndex; int high = toIndex - 1; while (low <= high) { int mid = (low + high) >>> 1; @SuppressWarnings("rawtypes") Comparable midVal = (Comparable)a[mid]; @SuppressWarnings("unchecked") int cmp = midVal.compareTo(key); if (cmp < 0) low = mid + 1; else if (cmp > 0) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found. }
List:Arrays.asList(arr).contains(targetValue),使用迴圈查詢
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Set:使用的是HashSet的contains方法(HashSet底層HashMap實現),通過hash值迴圈對比查詢
/**
* Implements Map.get and related methods
*
* @param hash hash for key
* @param key the key
* @return the node, or null if none
*/
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
ArrayUtils:ArrayUtils.contains(arr, targetValue),同樣使用迴圈實現查詢
public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
if (array == null) {
return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
}
if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
return INDEX_NOT_FOUND;
}
雖然大部分都是通過迴圈對比查詢,但通過簡單的程式碼測試,使用ArrayUtils.contains(arr, targetValue)是效能相對較高的選擇。
public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
if (array == null) {
return INDEX_NOT_FOUND;
}
if (startIndex < 0) {
startIndex = 0;
}
if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
return INDEX_NOT_FOUND;
}
public static void main(String[] args) {
String[] arr = { "AB", "BC", "CD", "DE", "EF" };
int loopTime = 10;
// 當被查詢的陣列容量比較小時,查詢耗時基本沒有太大差別
// 查詢10次
//useList : 331390
//useSet : 387718
//useLoop : 14571
//use ArrayBinary : 34738
//use ArrayUtils : 13755
// 查詢100000次
//useList : 42319492
//useSet : 204266488
//useLoop : 7266007
//use ArrayBinary : 11627486
//use ArrayUtils : 3777349
// 查詢10次,且大容量陣列
//useList : 7949871
//useSet : 42562837
//useLoop : 3443155
//use ArrayBinary : 83144
//use ArrayUtils : 53373
// 查詢10次,小容量陣列
//useList : 397205
//useSet : 926739
//useLoop : 22571
//use ArrayBinary : 44114
//use ArrayUtils : 17764
// arr = new String[10];
// Random random = new Random();
// for (int i = 0; i < arr.length; i++) {
// arr[i] = String.valueOf(random.nextInt());
// }
long startTime = System.nanoTime();
for (int i = 0; i < loopTime; i++) {
useList(arr, "A");
}
long endTime = System.nanoTime();
System.out.println("useList : " + (endTime - startTime));
startTime = System.nanoTime();
for (int i = 0; i < loopTime; i++) {
useSet(arr, "A");
}
endTime = System.nanoTime();
System.out.println("useSet : " + (endTime - startTime));
startTime = System.nanoTime();
for (int i = 0; i < loopTime; i++) {
useLoop(arr, "A");
}
endTime = System.nanoTime();
System.out.println("useLoop : " + (endTime - startTime));
startTime = System.nanoTime();
for (int i = 0; i < loopTime; i++) {
useArraysBinarySearch(arr, "A");
}
endTime = System.nanoTime();
System.out.println("use ArrayBinary : " + (endTime - startTime));
startTime = System.nanoTime();
for (int i = 0; i < loopTime; i++) {
useArraysBinarySearch(arr, "A");
}
endTime = System.nanoTime();
System.out.println("use ArrayUtils : " + (endTime - startTime));
System.out.println((1 + 10) >>> 1);
}
public static boolean useArrayUtils(String[] arr, String targetValue) {
return ArrayUtils.contains(arr, targetValue);
}
// 使用binarySearch需要有序
public static boolean useArraysBinarySearch(String[] arr, String targetValue) {
int a = Arrays.binarySearch(arr, targetValue);
if (a > 0) {
return true;
} else {
return false;
}
}
// 測試陣列包含測試
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<>(Arrays.asList(arr));
return set.contains(targetValue);
}
public static boolean useLoop(String[] arr, String targetValue) {
for (String str : arr) {
if (str.equals(targetValue)) {
return true;
}
}
return false;
}