• 七、如何在Java中高效检查一个数组是否含有一个值


    如何检查一个数组(非排序的)是否包含特定的值。这是个非常有用或经常被在Java中使用。这是个在Stack Overflow中高得票的问题。在已经高得票的答案中,有许多不同的处理方法,但是时间的复杂度非常不同。在下面,我将会展示每种方法的时间花费。

    一、四种不同的方法去检查一个数组包含特定的值

    1) 用List

    public static boolean useList(String[] arr, String targetValue) {

          return Arrays.asList(arr).contains(targetValue);

    }

    2)             用Set

    public static boolean useSet(String[] arr, String targetValue) {

          Set<String> set = new HashSet<String>(Arrays.asList(arr));

          return set.contains(targetValue);

    }

    3)             用简单的循环

    public static boolean useLoop(String[] arr, String targetValue) {

          for(String s: arr){

                if(s.equals(targetValue))

                      return true;

          }

          return false;

    }

    4)             用Arrays.binarySearch()

    下面的代码是错误的,列出来是为了完备性。BinarySearch()只能用在排序的数组上。你会觉得下面的代码运行的结果是怪异的。

    public static boolean useArraysBinarySearch(String[] arr, String targetValue) {    

          int a =  Arrays.binarySearch(arr, targetValue);

          if(a > 0)

                return true;

          else

                return false;

    }

    二、时间复杂度

    下面的近似的时间测量。下面的基本方法是测试查找一个数量为5、1k、10K。这种处理也许是不精确的,但是很清晰也很简单。

    public static void main(String[] args) {

          String[] arr = new String[] {  "CD",  "BC", "EF", "DE", "AB"};

          //use list

          long startTime = System.nanoTime();

          for (int i = 0; i < 100000; i++) {

                useList(arr, "A");

          }

          long endTime = System.nanoTime();

          long duration = endTime - startTime;

          System.out.println("useList:  " + duration / 1000000);

          //use set

          startTime = System.nanoTime();

          for (int i = 0; i < 100000; i++) {

                useSet(arr, "A");

          }

          endTime = System.nanoTime();

          duration = endTime - startTime;

          System.out.println("useSet:  " + duration / 1000000);

          //use loop

          startTime = System.nanoTime();

          for (int i = 0; i < 100000; i++) {

                useLoop(arr, "A");

          }

          endTime = System.nanoTime();

          duration = endTime - startTime;

          System.out.println("useLoop:  " + duration / 1000000);

          //use Arrays.binarySearch()

          startTime = System.nanoTime();

          for (int i = 0; i < 100000; i++) {

                useArraysBinarySearch(arr, "A");

          }

          endTime = System.nanoTime();

          duration = endTime - startTime;

          System.out.println("useArrayBinary:  " + duration / 1000000);

    }

    结果:

    useList:  13

    useSet:  72

    useLoop:  5

    useArraysBinarySearch:  9

    用大数组(1K):

    String[] arr = new String[1000];

     

    Random s = new Random();

    for(int i=0; i< 1000; i++){

          arr[i] = String.valueOf(s.nextInt());

    }

    结果:

    useList:  112

    useSet:  2055

    useLoop:  99

    useArrayBinary:  12

    用更大的数组(10K)

    String[] arr = new String[10000];

    Random s = new Random();

    for(int i=0; i< 10000; i++){

          arr[i] = String.valueOf(s.nextInt());

    }

    结果:

    useList:  1590

    useSet:  23819

    useLoop:  1526

    useArrayBinary:  12

    很明显,用简单的循环方法比用任何集合更有效。很多开发者用第一种方法,但是它是不高效的。传递数组给另外一个集合,在操作前,需要转换所有元素。

    如果一个数组是排序的。如果Arrays.binarySearch()方法被使用。

    在这种情况下,由于数组是没有排序的,所以它不能使用。

    实际上,如果你真的需要去高效查找一个值是否在一个数组或集合中,一个排序的list或tree 可以在O(log(n))或hashset 可以在O(1)完成。

  • 相关阅读:
    百度高级搜索技巧
    JRebel插件使用详解
    css3自适应布局单位vw,vh详解
    vue的MVVM原理
    JS实现全屏和退出全屏
    设置不定宽高的元素垂直水平居中
    微信小程序启动更新机制
    了解MVVM原理
    xss攻击和csrf攻击的定义及区别
    跨站脚本漏洞(XSS)基础讲解
  • 原文地址:https://www.cnblogs.com/seaspring/p/5268369.html
Copyright © 2020-2023  润新知