为什么 list.size()>0 比 Java 中的 list.isEmpty() 慢?

新手上路,请多包涵

为什么 list.isEmpty() list.size()>0 慢?换句话说,为什么 isEmpty() 优于 size()>0

当我查看 ArrayList 中的实现时,看起来速度应该是相同的:

ArrayList.size()

     /**
     * Returns the number of elements in this list.
     *
     * @return the number of elements in this list
     */
    public int size() {
      return size;
    }

ArrayList.isEmpty()

     /**
     * Returns <tt>true</tt> if this list contains no elements.
     *
     * @return <tt>true</tt> if this list contains no elements
     */
    public boolean isEmpty() {
        return size == 0;
     }

如果我们只是编写一个简单的程序来获取两种方法所花费的时间,那么在所有情况下 size() 将花费更多 isEmpty() ,为什么会这样?

这是我的测试代码;

 import java.util.List;
import java.util.Vector;

public class Main {
    public static void main(String[] args) {
        List l=new Vector();
        int i=0;
        for(i=0;i<10000;i++){
            l.add(new Integer(i).toString());
        }
        System.out.println(i);
        Long sTime=System.nanoTime();
        l.size();
        Long eTime=System.nanoTime();
        l.isEmpty();
        Long eeTime=System.nanoTime();
        System.out.println(eTime-sTime);
        System.out.println(eeTime-eTime);
    }
}

这里 eTime-sTime>eeTime-eTime 在所有情况下。为什么?

原文由 Ashish Agarwal 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 835
2 个回答

您的测试代码有缺陷。

只需颠倒顺序,即首先调用 isEmpty 和 size > 0 秒,您将得到 相反 的结果。这是由于类加载、缓存等。

原文由 JRL 发布,翻译遵循 CC BY-SA 2.5 许可协议

对于 ArrayList ,是的——你是正确的,这些操作花费(大致)相同的时间。

对于 List 的其他实现——例如,一个朴素的链表*——计算大小可能需要很长时间,而你实际上只关心它是否大于零。

因此,如果您绝对知道该列表是 ArrayList 的一个实现,并且永远不会改变,那么这并不重要;但:

  1. 这是将自己束缚于特定实现的糟糕编程习惯。
  2. 如果几年后随着代码重构发生变化,测试将显示“它有效”,但运行效率不如以前。
  3. 即使在最好的情况下, size() == 0 仍然不比 isEmpty() _快_,所以没有令人信服的理由去使用前者。
  4. isEmpty() 更清晰地定义了您真正关心和正在测试的内容,因此使您的代码更容易理解。

\* 我最初在这里编写 LinkedList,隐式引用 java.util.LinkedList ,尽管该特定实现确实明确存储了它的大小,使 size() 在这里成为 O(1) 操作。天真的链表操作可能不会这样做,并且在更一般的意义上, List 的实现没有效率保证。

原文由 Andrzej Doyle 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题