• Java中数组判断元素存在几种方式比较详解


    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进行操作,虽然说相对相率低一点,但是还会不会差很多。  

     

  • 相关阅读:
    证书格式转换
    emq知识点
    emq共享订阅
    SpringBoot
    Android网络编程Socket长连接
    Android 网络通信框架Volley简介(Google IO 2013)
    Android中的5种数据存储方式
    Android
    android解析XML总结(SAX、Pull、Dom三种方式)
    乔迁新禧
  • 原文地址:https://www.cnblogs.com/lonecloud/p/9290013.html
Copyright © 2020-2023  润新知