1. 程式人生 > >Java 判斷陣列是否包含某個值

Java 判斷陣列是否包含某個值

參照連結: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;
  }