java集合list中添加list_Java集合------List集合

一、List接口

List接口直接继承Collection接口,代表有序的Collection。

public interface List extends Collection {}

是一个有序的允许重复的集合,可以通过索引查找list中的具体元素。在开发中常用实现类有:ArrayList、LinkedList、Vector:

ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。

LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率低。

Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。

1.常用的方法

add():在列表的最后添加元素;

add(index,obj):将指定的元素插入此列表中的指定位置;

size():返回当前列表的元素个数

get(int index):返回下标为index的元素;

set(index,obj):用新传入的对象,将指定位置的元素替换掉,返回被替换前的元素对象;

remove():传入一个下标,或者一个对象,删除指定元素;

如果删除指定对象,需要重写equals()方法,比对传入的对象是不是属于原列表,如果属于,结果返回true;

clear():清除列表中所有元素;

isEmpty():检测列表是否为空;返回true/false;

contains():传入一个对象,检测列表中是否含有该对象;

indexOf():传入一个对象,返回该对象在列表中首次出现的地址;

lastInsevOf():传入一个对象,返回该对象在列表中最后一次出现的地址;

subList( int fromIndex , int toIndex) :截取一个子列表返回List类型;

toArray():将列表转为数组,返回一个Object[]类型;

iterator():使用迭代器遍历。

2.List使用场景

应当根据实际操作场景和需要具体考虑选用List的实现类 (涉及“栈” 、“队列” 、“链表”等):

(1)需要快速插入、删除元素,应该使用LinkedList, LinkedList是有序的,增删快、查询慢

(2)对于需要快速随机访问元素,应使用ArrayList,ArrayList是无序的,查询块、增删慢

(3)对于“单线程环境” 或者:“多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类,如ArrayList

Vector是支持同步的,Stack继承于Vector。

二、ArrayList集合

ArrayList是一个动态数组,elementDate就是底层数组,其初始的容量为10 ,也就是未定义时数组的大小。随着数组中元素的不断增加,数组的容量的大小也会随

着增加。在每次向容器中增加元素的同时,会对ArrayList进行容量检查,当快溢出时,就会进行扩容操作。在定义数组时,一般要定义数组的初始值,减少因元素个素

超过数组初始大小时进行扩容操作而浪费时间、效率。

图解:

java集合list中添加list_Java集合------List集合_第1张图片

ArrayList的get(int index)、set(int index, E element)、

的固定时间运行,添加n个元素需要O(n)时间,要考虑到扩容,所以时间不仅仅只是添加元素分摊固定时间。

ArrayList类似于数组,存储的数据在内存中是连续的、成块的、查找的时候直接遍历内存就可以;而插入删除的时候,就要把修改的那个节点之后的所有数据都向

后移,或者向前移。

1.线程不安全

ArrayList 是基于动态数组的集合。ArrayList查询速度非常快,使得它在实际开发中被广泛使用,但它并不是线程安全的。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//查询元素

public E get(intindex) {

rangeCheck(index);//检查是否越界

returnelementData(index);

}//顺序添加元素

public booleanadd(E e) {

ensureCapacityInternal(size+ 1); //扩容机制

elementData[size++] =e;return true;

}//从数组中间添加元素

public void add(intindex, E element) {

rangeCheckForAdd(index);//数组下标越界检查

ensureCapacityInternal(size + 1); //扩容机制

System.arraycopy(elementData, index, elementData, index + 1, size - index); //复制数组

elementData[index] = element; //替换元素

size++;

}//从数组中删除元素

private void fastRemove(intindex) {

modCount++;int numMoved = size - index - 1;if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index, numMoved);

elementData[--size] = null; //clear to let GC do its work

}

View Code

由于ArrayList是非同步的,没有同步锁;在多线程的情况下,调用这个方法时,可能会有可能被多个线程拿到相同的size值去与ArrayList的容量做比较,而执行到

elemntData[size++] = e;时却是有序的,这时由于没有适当的扩大ArrayList的容量,从而导致插入数据的长度大于ArrayList的剩余容量,于是抛出了数组越界异常

(java.lang.ArrayIndexOutOfBoundsException)。

一个ArrayList,在添加一个元素的时候,它有可能会分为两步来完成:

(1)在Items[size]的位置存放此元素

(2)增大Size值

在单线线程运行的情况下,如果size=0,添加一个元素后,此元素在位置0,而且size=1;

而如果在多线程情况下,比如有两个线程,线程A先将元素存放在位置0。但是此时CPU调度线程A暂停,线程B得到运行的机会。线程B也向此ArrayList添加元素,

因为此时size仍然等于0(假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都

增加 Size 的值。现在看ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。

线程不安全的解决:

如果需要在多线程中使用,可以采用Collections.synchronizedList()方法

List> data=Collections.synchronizedList(new ArrayList>());

三、LinkedList集合

LinkedList是List接口的链表实现,首尾相接,可以作为栈、队列、双端队列数据结构使用,本质是双向链表,不能像ArrayList一样随意访问查询;包含两个重要的

成员:header 和 size。header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。Entry中包含成员变量: previous, next, element。其中,previous是

该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。size是双向链表中节点的个数。LinkedList非同步,线程不安全.

java集合list中添加list_Java集合------List集合_第2张图片

查询慢、增删快

LinkedList 其实是一个个的Node节点,每个Node节点首位相连

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//查询元素

public E get(intindex) {

checkElementIndex(index);//检查是否越界

returnnode(index).item;

}

Node node(intindex) {if (index < (size >> 1)) { //类似二分法

Node x =first;for (int i = 0; i < index; i++)

x=x.next;returnx;

}else{

Node x =last;for (int i = size - 1; i > index; i--)

x=x.prev;returnx;

}

}//插入元素

public void add(intindex, E element) {

checkPositionIndex(index);//检查是否越界

if (index == size) //在链表末尾添加

linkLast(element);else //在链表中间添加

linkBefore(element, node(index));

}void linkBefore(E e, Nodesucc) {final Node pred =succ.prev;final Node newNode = new Node<>(pred, e, succ);

succ.prev=newNode;if (pred == null)

first=newNode;elsepred.next=newNode;

size++;

modCount++;

}

View Code

当进行数组循环时,ArrayList以及数组,适合用for循环下标遍历,当用for大批量的循环LinkedList时,程序会卡死

LinkedList适合用foreach循环        (队列 : 先进先出     栈:先进后出)

四、Vector

Vector的数据结构和ArrayList相似,操作基本与ArrayList一致,但是其对数据操作的方法基本上都被synchronized关键字修饰,所以是线程安全的,所以相比较

于ArrayList而言,性能要低。若想要一个高性能,又是线程安全的ArrayList,可以使用Collections.synchronizedList(list),方法或者使用CopyOnWriteArrayList集合。

你可能感兴趣的:(java集合list中添加list_Java集合------List集合)