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

2022-08-31 17:05:04

为什么比Java慢?换句话说,为什么比更可取?list.size()>0list.isEmpty()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


答案 1

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

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

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

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

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


答案 2

您的测试代码存在缺陷。

只需颠倒顺序,即调用 isEmpty 第一,大小> 0 秒,你会得到相反的结果。这是由于类加载,缓存等。