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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。