使用ArrayList或TreeSet优化代码?

时间:2014-04-12 22:01:02

标签: java optimization data-structures arraylist treeset

TreeMap<String,ArrayList<String>> statesToPresidents = new TreeMap<String,ArrayList<String>>();
    TreeMap<String,String> reversedMap = new TreeMap<String,String>();
    TreeSet<String> presidentsWithoutStates = new TreeSet<String>();
    TreeSet<String>statesWithoutPresidents = new TreeSet<String>(); while (infile2.ready())
    {
        String president = infile2.readLine();
        if (reversedMap.containsKey(president)==false)
            presidentsWithoutStates.add(president);
    }

    infile2.close();

    System.out.println( "\nThese presidents were born before the states were formed:\n");  // DO NOT REMOVE OR MODIFY

    // YOUR CODE HERE TO PRINT THE NAME(S) Of ANY PRESIDENT(s)
    //  WHO WERE BORN BEFORE THE STATES WERE FORMED = 10%

    Iterator<String> iterator = presidentsWithoutStates.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }

我想知道如果我使用ArrayList而不是TreeSet,我的程序是否会运行得更快。我将字符串President添加到presidentWithoutStates TreeSet中,如果它不是rev​​erseMap中的键,当我打印出来时我需要按顺序排序。我应该使用TreeSet并按照我的方式进行排序,或者我应该使用arraylist而不是在最后排序。我看到了一个类似的问题,但那个人并没有像我一样不断添加元素。

编辑:没有重复

1 个答案:

答案 0 :(得分:4)

让我们打破运行时间:

<强>的ArrayList:

  • n插入每个分摊O(1),给我们O(n)

  • 排序需要O(n log n),假设您使用内置的Collections.sortO(n log n)排序算法。

  • 通过O(n)

  • 进行迭代

总计= O(n + n log n) = O(n log n)

<强> TreeSet中:

  • n每次点击O(log n),向我们O(n log n)

  • 通过O(n)

  • 进行迭代

总计= O(n log n + n) = O(n log n)

<强>结论:

渐近地,我们有相同的表现。

在实践中,ArrayList可能会稍快一些。

我为什么这么说?好吧,让我们假设它不是。然后我们可以使用TreeSet对数组进行排序的速度比专门对其进行排序的方法更快(从不必插入ArrayList得到的节省相当小)。这看似违反直觉,不是吗?如果这是(一贯)真的,Java开发人员只会用TreeSet替换该方法,不会吗?

人们可以分析排序与TreeSet相关的常数因素,但这可能相当复杂,程序运行的条件也会影响常数因子,因此它可以&#39;确切地说。

关于重复的说明:

以上假设没有任何重复。

如果有重复项,如果您要使用contains,则绝对不应该进行ArrayList检查,而是事后进行重复删除(这可以通过简单的方式完成)忽略排序后迭代期间连续的连续元素)。应该避免contains检查的原因是因为它需要O(n),这可能会使整个事情需要O(n²)

如果有很多重复项,TreeSet可能会更快,因为它只需要O(n log m),其中m是重复项的数量。排序选项不会直接处理重复项,因此,除非m非常小,否则您很幸运,最终仍然需要O(n log n)

TreeSet变得比排序选项更快的确切点确实是基准测试。