java中的arraylist是做什么的,java中array和arraylist的区别

  java中的arraylist是做什么的,java中array和arraylist的区别

  

  什么情况用ArrayList or LinkedList呢?

  ArrayList和LinkedList是Java集合框架中用来存储对象引用列表的两个类。ArrayList和LinkedList都实现了List接口。首先,对List做一个简单的理解:

  列表是元素的有序集合,也称为序列。它提供了基于元素位置的操作,这有助于快速访问、添加和删除列表中特定索引位置的元素。List接口实现Collection和Iterable作为父接口。它允许存储重复值和空值,并支持通过索引访问元素。

  读完本文要明确的问题:ArrayList和LinkedList有什么区别?什么时候应该使用ArrayList,什么时候应该使用LinkedList?

  (推荐视频:java视频教程

  下面以增加和删除元素为例比较ArrayList和LinkedList的不同之处

  将元素添加到列表末尾:

  在ArrayList中增加元素到队列尾端的代码如下:

  公共布尔加法(E e){

  确保容量(尺寸1);//确保内部数组有足够的空间

  element data[size]=e;//将元素添加到数组的末尾,完成加法运算

  返回true

  }ArrayList中add()方法的性能取决于ensureCapacity()方法。EnsureCapacity()的实现如下:

  公共视频点播保障容量(int minCapacity){

  modCount

  int old capacity=element data . length;

  If(minCapacityoldCapacity){ //如果数组容量不足,请将其扩展。

  object[]old data=element data;

  int new capacity=(old capacity * 3)/2 1;//扩展到原来容量的1.5倍。

  If(new capacity min capacity)//如果新容量小于最小所需容量,则使用最小值

  //所需的容量大小

  newCapacity=minCapacity//复制扩展的数组

  element data=arrays . copy of(element data,new capacity);

  }

  }大家可以看到,只要ArrayList当前的容量足够大,add()运算的效率是很高的。只有当ArrayList对容量的需求超过当前数组大小时,才需要扩展。在扩展的过程中,会进行大量的数组复制操作。但是在复制数组时,最终会调用System.arraycopy()方法,所以add()操作的效率相当高。

  LinkedList 的add()操作实现如下,它也将任意元素增加到队列的尾端:

  公共布尔加法(E e){

  addBefore(e,header);//将元素添加到标头的前面

  返回true

  }其中addBefore()的方法实现如下:

  私有条目添加之前(例如,条目条目){

  EntryE newEntry=new EntryE(e,Entry,entry . previous);

  new entry . provious . next=new entry;

  new entry . next . previous=new entry;

  尺寸;

  modCount

  返回newEntry

  }可以看出,LinkeList因为使用了链表结构,所以不需要维护其容量的大小。从这个角度来说,它比ArrayList有一定的性能优势。但是,每次添加一个元素,都需要创建一个新的Entry对象,并且需要执行更多的赋值操作。频繁的系统调用会对性能产生一定的影响。

  增加元素到列表任意位置

  List接口除了提供元素到列表末尾,还提供了在任意位置插入元素的方法:void add(int index,E element);

  由于实现的不同,ArrayList和LinkedList在这个方法上有一定的性能差异。因为ArrayList是基于array实现的,array是一个连续的内存空间,如果你在数组的任意位置插入元素,必然会造成那个位置之后的所有元素都被重排,所以它的效率会比较低。

  以下代码是ArrayList中的实现:

  public void add(int index,E element){

  if(indexsizeindex0)

  抛出新的IndexOutOfBoundsException(

  Index: index ,size: size);

  确保容量(尺寸1);

  System.arraycopy(elementData,index,elementData,index 1,size-index);

  element data[index]=element;

  尺寸;

  }你可以看到,每一次插入操作,都会产生一个数组副本。在列表末尾添加元素时不存在这种操作,大量的数组重组操作会导致系统性能低下。并且插入元素在列表中的位置越高,数组重组的代价就越高。

  而LinkedList此时显示了优势:

  public void add(int index,E element){

  addBefore(元素,(index==size?header:entry(index)));

  }可以看出,对于LinkedList来说,在列表末尾插入数据和在任意位置插入数据是一样的,插入方法的性能不会因为插入位置在前面而降低。

  删除任意位置元素

  对于元素的删除,列表界面提供了删除任意位置元素的方法:

  public E remove(int index);对于ArrayList,remove()方法和add()方法是相同的。在移除任何位置的元素后,必须重组数组。ArrayList的实现如下:

  public E remove(int index){

  RangeCheck(索引);

  modCount

  E old value=(E)element data[index];

  int num moved=size-index-1;

  if(numMoved0)

  System.arraycopy(elementData,index 1,elementData,index,num moved);

  element data[-size]=null;

  返回旧值;

  }可以看到,ArrayList的每一次有效元素删除操作之后,数组都要重新组织。而且删除的位置越高,数组重组的成本越高。

  public E remove(int index){

  return remove(条目(索引));

  }

  私有条目(int index){

  if(index0 index=size)

  抛出新的IndexOutBoundsException( Index: Index ,size: size);

  EntryE=header;

  If(index(size1)){//要删除的元素在前半部分。

  for(int I=0;I=指数;我)

  e=e . next;

  }否则{

  for(int I=size;iindex我-)

  e=e . prior;

  }

  返回e;

  }在LinkedList的实现中,首先要通过一个循环找到要删除的元素。如果要删除的位置在列表的前半部分,从前向后看;如果它的位置在后半部分,从后往前看。因此,删除较早或较晚的元素是非常高效的。但是,删除列表中间的元素几乎需要列表的一半,这在列表有大量元素时效率很低。

  容量参数

  capacity参数是基于数组的列表(如ArrayList和Vector)的唯一性能参数。它表示初始化的数组大小。当存储在ArrayList中的元素数量超过其现有大小时。它将被扩展,数组的扩展将导致整个数组的内存副本。因此,合理的阵列大小有助于减少阵列扩展的次数,从而提高系统性能。

  公共数组列表(){

  这(10);

  }

  公共数组列表(int initialCapacity){

  super();

  if(initialCapacity0)

  抛出新的IllegalArgumentException(非法容量: initialCapacity )

  this . element data=new Object[initial capacity];

  }ArrayList提供了一个构造函数,可以使初始数组大小:

  public ArrayList(int initial capacity)现在以构造一个100万元素的列表为例。当使用默认的初始化大小时,消耗的相对时间大约是125毫秒。当数组大小直接为100万时,构造同一个ArrayList只需要16ms。

  遍历列表

  遍历列表是最常用的列表操作之一。在JDK1.5之后,至少有三种常用的列表遍历方法:

   forEach操作

  迭代器

   for循环。

  字符串tmp

  long start=system . current time mills();//ForEach

  for(String s:list){

  tmp=s;

  }

  system . out . println( foreach spend:(system . current time mills()-start));

  start=system . current time mills();

  for(iterator string it=list . iterator();it . has next();){

  tmp=it . next();

  }

  system . out . println( Iterator spend;(system . current time mills()-start));

  start=system . current time mills();

  int size=;list . size();

  for(int I=0;isizei ){

  tmp=list . get(I);

  }

  system . out . println( for spend;(system . current time mills()-start));用一百万个数据构造一个ArrayList及其等价的LinkedList,用上面的代码测试。测试结果如下:

  如何解决写爬虫IP受阻的问题?立即使用。

  什么情况用ArrayList or LinkedList呢?

  如您所见,最简单的ForEach循环并没有很好的性能。其综合性能不如普通迭代器。而是用for循环通过随机访问遍历列表的时候,ArrayList条目很好,但是LinkedList的性能无法接受,没有办法等到程序结束。这是因为当您随机访问LinkedList时,您将总是遍历列表一次。性能很差,应该避免。

  总结

  ArrayList和LinkedList在性能上各有优劣,都有各自适用的地方。一般来说,它们可以描述如下:

  1.对于ArrayList和LinkedList,在列表末尾添加一个元素的开销是固定的。

  对于ArrayList,主要是在内部数组中添加一个项,指向添加的元素,偶尔可能会导致数组被重新分配;

  对于LinkedList,这种开销是统一的,并且分配一个内部条目对象。

  2.在ArrayList中间插入或删除一个元素意味着这个列表中剩余的元素将被移动;而在LinkedList中间插入或删除元素的开销是固定的。

  3.链表不支持高效的随机元素访问。

  4.4的空间浪费。ArrayList主要体现在列表末尾预留一定的容量空间,而LinkedList的空间开销则体现在它的每个元素都需要消耗相当大的空间。

  本文来自我们,java教程专栏,欢迎学习!也就是java中什么时候使用ArrayList和LinkedList?更多详情请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: