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

     

  • 相关阅读:
    win7下的vxworks总结
    ubuntu 无法获得锁 /var/lib/dpkg/lock
    项目中用到了的一些批处理文件
    win7下安装 WINDRIVER.TORNADO.V2.2.FOR.ARM
    使用opencv统计视频库的总时长
    January 05th, 2018 Week 01st Friday
    January 04th, 2018 Week 01st Thursday
    January 03rd, 2018 Week 01st Wednesday
    January 02nd, 2018 Week 01st Tuesday
    January 01st, 2018 Week 01st Monday
  • 原文地址:https://www.cnblogs.com/lonecloud/p/9290013.html
Copyright © 2020-2023  润新知