1. 通过将数组转换成 List, 然后使用 List 中的 contains 进行判断其是否存在
- public static boolean useList(String[] arr,String containValue){
- return Arrays.asList(arr).contains(containValue);
- }
需要注意的是 Arrays.asList 这个方法中转换的 List 并不是 java.util.ArrayList 而是 java.util.Arrays.ArrayList, 其中 java.util.Arrays.ArrayList 中不能对数组的长度进行扩容操作, 这个尤为重要, 其中 contains 实现如下:
- @Override
- public boolean contains(Object o) {
- // 调用 indexOf 方法判断其在那个位置, 判断其时候为 - 1
- return indexOf(o) != -1;
- }
- @Override
- public int indexOf(Object o) {
- // 获取元素
- E[] a = this.a;
- // 判断空
- if (o == null) {
- // 循环判断
- for (int i = 0; i <a.length; i++)
- // 如果元素为 null
- if (a[i] == null)
- // 则返回
- return i;
- } else {
- // 如果其不为空
- for (int i = 0; i < a.length; i++)
- // 判断元素与 a[i] 是否相等
- if (o.equals(a[i]))
- // 相等返回 i
- return i;
- }
- // 否则返回 - 1
- return -1;
- }
2. 使用 Set 进行实现判断是否存在
- public static boolean useSet(String[] arr,String containValue){
- return new HashSet<>(Arrays.asList(arr)).contains(containValue);
- }
原理将数组 ->List->Set 使用 Set 进行比较
源码: 通过调用 map 的 containsKey 实现的, 而 hashmap 中则是通过遍历 hash 表中的 key 实现
- ypublic boolean contains(Object o) {
- return map.containsKey(o);
- }
3. 使用循环来实现, 自己编写一个循环来判断
- public static boolean useLoop(String[] arr,String containValue){
- // 判断是否为空
- if (arr==null||arr.length==0){
- return false;
- }
- for (int i = 0; i <arr.length; i++) {
- //all null
- if (containValue!=null&&containValue.equals(arr[i])){
- return true;
- }else if (arr[i]==null){
- return true;
- }
- }
- return false;
- }
4. 使用 org.apache.commons.lang3.ArrayUtils 中的 contains 方法来实现
- public static boolean useUtils(String[] arr,String containValue){
- return ArrayUtils.contains(arr,containValue);
- }
具体实现源码:
- public static boolean contains(final Object[] array, final Object objectToFind) {
- // 调用 indexof 进行判断位置
- return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
- }
- public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
- // 判断 null
- if (array == null) {
- return INDEX_NOT_FOUND;
- }
- // 判断起始位置
- if (startIndex < 0) {
- startIndex = 0;
- }
- // 判断查询元素是否为 null
- if (objectToFind == null) {
- //null 则直接使用 == 进行循环判断位置
- for (int i = startIndex; i < array.length; i++) {
- if (array[i] == null) {
- return i;
- }
- }
- // 判断元素是不是 array 中的元素的实例, 如果是则循环并采用 equals 进行判断
- } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
- for (int i = startIndex; i < array.length; i++) {
- if (objectToFind.equals(array[i])) {
- return i;
- }
- }
- }
- // 返回没有找到
- return INDEX_NOT_FOUND;
- }
使用循环 1w 次来检测效率
- public static void reCompileArr(String[] arr,String containValue){
- //using List
- long start = System.nanoTime();
- for (int i = 0; i < 10000; i++) {
- useList(arr,containValue);
- }
- long end=System.nanoTime();
- System.out.println("using list->"+(end-start)/10000);
- //using set
- start = System.nanoTime();
- for (int i = 0; i <10000; i++) {
- useSet(arr,containValue);
- }
- end=System.nanoTime();
- System.out.println("using set->"+(end-start)/10000);
- //using loop
- start = System.nanoTime();
- for (int i = 0; i <10000; i++) {
- useLoop(arr,containValue);
- }
- end=System.nanoTime();
- System.out.println("using loop->"+(end-start)/10000);
- //using utils
- start = System.nanoTime();
- for (int i = 0; i <10000; i++) {
- useUtils(arr,containValue);
- }
- end=System.nanoTime();
- System.out.println("using utils->"+(end-start)/10000);
- }
结果如下图:
- using list->973
- using set->2676
- using loop->448
- using utils->1364
使用的 jdk 版本为 jdk1.8.0_172 版本, 由上面可以推断出来
以上四种方法的效率高 -> 低
loop>list>utils>set
对比之下, 其实可以看出, 采用 loop 方法进行判断的效率最高, 再过去 list, 再过去 utils 再过去 set
总结:
分析一下慢的原因:
loop 最快, 直接操作 array, 毫无疑问
list 次之, 由于需要创建一个 java.util.Array.ArrayList, 创建对象需要时间所以会更慢一些
util 第三, 由于其虽然使用的和 loop 差不多, 但是 array.getClass().getComponentType().isInstance(objectToFind), 该段代码采用调用了本地 native 方法, 我们知道, 通过调用本地 native 方法会比直接调用 java 方法更加耗时. 而且查看源码可知 getClass() 与 getComponentType() 以及 isInstance 都是 native 方法, 非常耗时
set 最差, 由于其先将 Array 转换成 List, 再讲 list 转换成 Set, 在 Set 中又是采用 HashMap 来实现的, 由于其多次转换对象, 自然, 效率也肯定好不到哪里去了.
其实我个人还是比较喜欢使用 ArrayUtils 进行操作, 虽然说相对相率低一点, 但是还会不会差很多.
来源: https://www.cnblogs.com/lonecloud/p/9290013.html