Java Collection-ArrayList 和 Vector 之间的加速

标签 java performance arraylist collections

从一些资源中,我了解到在Java集合下,ArrayListVector 快。为了检查这一点,我尝试使用一个小程序,其中一种方法将一些数据添加到 ArrayList 中。然后检索这些数据,另一种方法将相同的数据添加到 Vector 或从中检索相同的数据。现在main()方法在两个不同的时间计算过程下调用其中两个方法,分别计算这些方法的执行时间。结果,我得到 ArrayList 的执行时间是 18385831 ns,Vector是 2190242 纳秒。我的项目负责人还说 ArrayListVector 快。但我的程序的结果却说了一些不同的东西。谁能向我解释正确的事情及其原因吗?也是这个结果的原因如果 ArrayList确实比 Vector 快.

这是我的源代码:

import java.util.*;

public class TestArraylist {

    void Arraylistpart() {
        ArrayList<Object> a1 = new ArrayList<Object>();
        ArrayList<Object> a2 = new ArrayList<Object>();
        a2 = a1;

        a1.add(1);
        a1.add('c');
        a1.add("gh");
        a1.add(2);
        a1.set(2, "ab");
        int count = 0;
        System.out.println(a1);
        try {
            for (Object i : a1) {
                a2.set(count, i.toString());
                count = count + 1;
            }
            a2.sort(null);
            System.out.println(a2);
        } catch (ClassCastException e) {
            System.err.println("Exception occurs");
        }
    }

    void vectorpart() {
        Vector<Object> v1 = new Vector<Object>();
        Vector<Object> v2 = new Vector<Object>();
        v2 = v1;
        v1.add(1);
        v1.add('c');
        v1.add("ab");
        v1.add(2);
        int count1 = 0;
        System.out.println(v1);
        try {
            for (Object i : v1) {
                v2.setElementAt(i.toString(), count1);
                count1 = count1 + 1;
            }
            v2.sort(null);
            System.out.println(v2);
        } catch (ClassCastException e) {
            System.err.println("Exception occurs");
        }
    }

    public static void main(String[] args) {
        TestArraylist objct = new TestArraylist();
        System.out.println("Arraylist program");
        long startmili = System.currentTimeMillis();
        long starttime = System.nanoTime();
        objct.Arraylistpart();
        long endtime = System.nanoTime();
        long endmili = System.currentTimeMillis();
        long totaltime = endtime - starttime;
        long totaltimemili = endmili - startmili;
        System.out.println(totaltime);
        System.out.println("Time in mili is: " + totaltimemili);

        System.out.println("\nVector program");
        long startmili1 = System.currentTimeMillis();
        long starttime1 = System.nanoTime();
        objct.vectorpart();
        long endtime1 = System.nanoTime();
        long endmili1 = System.currentTimeMillis();
        long totaltime1 = endtime1 - starttime1;
        long totaltimemili1 = endmili1 - startmili1;
        System.out.println(totaltime1);
        System.out.println("Time in mili is: " + totaltimemili1);
    }
}

最佳答案

你的基准是错误的。首先,您不仅测量了基于数组/vector 的操作的时间,还测量了打印时间,这可能比其他所有操作都要慢几个数量级。其次,您没有进行预热,因此您的大部分代码可能是由解释器执行的,而不是 JIT 编译的。第三,在同一个 JVM 中启动两个测试,将它们置于不平等的条件下:在第一个测试执行期间,JVM 执行更多的预热步骤(例如 JIT 编译),因此第一个测试从一开始就受到阻碍。让我们尝试使用 JMH 编写一些等效的内容。 :

import org.openjdk.jmh.annotations.*;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Warmup(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Fork(1)
@State(Scope.Benchmark)
public class TestArraylist {

    @Benchmark
    public String Arraylistpart() {
        ArrayList<Object> a1 = new ArrayList<>();
        ArrayList<Object> a2 = new ArrayList<>();
        a2 = a1;

        a1.add(1);
        a1.add('c');
        a1.add("gh");
        a1.add(2);
        a1.set(2, "ab");
        int count = 0;
        for (Object i : a1) {
            a2.set(count, i.toString());
            count = count + 1;
        }
        a2.sort(null);
        return a1.toString()+a2.toString();
    }

    @Benchmark
    public String vectorpart() {
        Vector<Object> v1 = new Vector<>();
        Vector<Object> v2 = new Vector<>();
        v2 = v1;
        v1.add(1);
        v1.add('c');
        v1.add("ab");
        v1.add(2);
        int count1 = 0;
        for (Object i : v1) {
            v2.setElementAt(i.toString(), count1);
            count1 = count1 + 1;
        }
        v2.sort(null);
        return v1.toString()+v2.toString();
    }
}

我返回了 a1.toString()+a2.toString() 而不是打印以保留 .toString() 调用(这是在您的测试中完成的 System.out.println)。

总结结果如下:

Benchmark                    Mode  Cnt  Score   Error  Units
TestArraylist.Arraylistpart  avgt   20  0,382 ± 0,003  us/op
TestArraylist.vectorpart     avgt   20  0,421 ± 0,002  us/op

看,您的测试实际上执行得快得多。只有382纳秒和421纳秒。由于额外的同步,Vector 确实有点慢。但似乎C2 JIT编译器很好地删除了一些不必要的同步部分,因此时间差异不是很大。检查每次迭代的统计数据也很有趣。对于ArrayList:

# Warmup Iteration   1: 0,544 us/op
# Warmup Iteration   2: 0,471 us/op
# Warmup Iteration   3: 0,383 us/op
# Warmup Iteration   4: 0,377 us/op
# Warmup Iteration   5: 0,377 us/op
# Warmup Iteration   6: 0,373 us/op
...
Iteration  14: 0,374 us/op
Iteration  15: 0,376 us/op
Iteration  16: 0,381 us/op
Iteration  17: 0,376 us/op
Iteration  18: 0,379 us/op
Iteration  19: 0,383 us/op
Iteration  20: 0,385 us/op

对于 vector :

# Warmup Iteration   1: 0,889 us/op
# Warmup Iteration   2: 0,630 us/op
# Warmup Iteration   3: 0,689 us/op
# Warmup Iteration   4: 0,662 us/op
# Warmup Iteration   5: 0,671 us/op
# Warmup Iteration   6: 0,673 us/op
# Warmup Iteration   7: 0,669 us/op
# Warmup Iteration   8: 0,657 us/op
# Warmup Iteration   9: 0,427 us/op
# Warmup Iteration  10: 0,421 us/op
# Warmup Iteration  11: 0,421 us/op
...
Iteration  17: 0,423 us/op
Iteration  18: 0,420 us/op
Iteration  19: 0,422 us/op
Iteration  20: 0,419 us/op

如您所见,ArrayList 在第 3 次迭代中达到全速,而 Vector 在第 9 次迭代中达到全速。

关于Java Collection-ArrayList 和 Vector 之间的加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35788759/

相关文章:

数字和破折号的 Java 正则表达式

java - 如何在 RecyclerView 的 ViewHolder 中正确实例化 mContentView,以避免空对象引用?

java - Android HttpClient 持久性 cookie

java - 尝试将 int 数组的内容复制到 Dimension 数组会导致 NullPointerException

SQL:排除的性能比较(加入与不加入)

java - 通过java从mysql的数据创建json对象

java - 将 IndexOf 与 arrayList 中的 customObject 一起使用

python - 如何提高时间序列重合过滤的性能?

python - Pandas 应用使用最小/最大在可变滚动窗口上执行缓慢

android - 我的 ArrayList 中的唯一值