繁体   English   中英

ArrayList与HashSet的性能

[英]Performance of ArrayList vs HashSet

我知道当我们需要存储重复项时,我们更喜欢使用ArrayList不是HashSet ,而HashSet使用hashCode()函数来计算其数组中每个元素的索引。

因此,这意味着如果我们想要存储单个元素,那么ArrayList应该比HashSet花费更少的时间。 如果我在任何地方都错了,请纠正我。

但是当我通过代码检查性能时,我会得到不同的行为。

情况1:

import java.util.*;
class HashsetVSArraylist
{
 public static void main(String args[])
 {
  ArrayList<Integer> a1=new ArrayList<Integer>();
  long nanos = System.nanoTime();

  a1.add(1);

  System.out.println("ArrayList Time:"+(System.nanoTime()-nanos)+"ns");

  HashSet<Integer> h1=new HashSet<Integer>();
  nanos = System.nanoTime();

  h1.add(2);

  System.out.println("HashSet Insertion Time:"+(System.nanoTime()-nanos)+"ns");
 }
}
Output:
ArrayList Time:495087ns
HashSet Insertion Time:21757ns

案例2:

import java.util.*;
class HashsetVSArraylist
{
 public static void main(String args[])
 {
  HashSet<Integer> h1=new HashSet<Integer>();
  long nanos = System.nanoTime();

  h1.add(2);

  System.out.println("HashSet Insertion Time:"+(System.nanoTime()-nanos)+"ns");

  ArrayList<Integer> a1=new ArrayList<Integer>();
  nanos = System.nanoTime();

  a1.add(1);

  System.out.println("ArrayList Time:"+(System.nanoTime()-nanos)+"ns");
 }
}
Output:
HashSet Insertion Time:582527ns
ArrayList Time:21758ns

现在,我假设HashSet应该花更多时间插入单个元素。 但是,在这两种情况下,行为都是不同的......代码中排在第二位的数据结构花费的时间更少。 此外,当插入的元素数量超过1000时,行为也会更改。

请解释一下发生了什么。

你的基准打破了。 阅读: 动态编译和性能测量以及:在尝试使用Java进行基准测试之前,对有缺陷的微基准测试进行剖析

简短的解释是,你要衡量有总持续时间是非常非常太短,和基准测试结果将通过微小的OS和CPU细节被淹没,并通过一个事实,即Java虚拟机仍忙于编译字节码在开始运行时加工代码。

同时,这是一个有点疯狂的时候,他们有两个不同的目的来比较ArrayList和HashList性能,但所有其他条件相同,ArrayList中的实现是显著更简单 ,所以你的假设是无疑是正确的; 它会更快。

这里的真正问题是Java在将整数原语转换为Integer对象时所做的自动装箱。

当你调用a1.add(1)时,这实际上是调用a1.add(Integer.valueOf(1))

第一次引用Integer类的静态valueOf方法时,导致在Integer类中执行静态初始化程序,这会创建数百个静态对象,并且在系统上大约需要500ms。

即便如此,在幕后还会发生许多干扰此测试的其他事情,例如其他静态初始化器,动态内存分配,系统资源分配以及无数其他。

如果你可以设计一个消除或最小化这些变量的测试,那么你会发现从长远来看,ArrayList的添加总是比HashSet快,但对于任何给定的插入都没有。 幸运的是,我们永远不应该关心单次插入的速度。

例如,想象一下尝试向ArrayList添加值的几乎最坏的情况,但是ArrayList是它的最大分配大小。 ArrayList尝试分配更多空间,但系统已达到当前内存分配上限,因此需要等待VM为系统分配更多内存。 同时垃圾收集器开始了。 在这种情况下,通常可能需要<1ms的插入可能需要多秒才能执行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM