多平台统一管理软件接口,如何实现多平台统一管理软件接口
311
2022-08-30
学习Java中的List集合
目录1.概述2.List的使用2.1List的常用方法3.List的实现类3.1ArrayList3.2Vector3.3LinkedList3.4ArrayList与Vector的区别
1.概述
List是一个有序集合(也被称为序列)。此接口的用户在列表中的每个元素都被插入的地方有精确的控制。用户可以通过它们的整数索引(在列表中的位置)访问元素,并在列表中搜索元素。 说是List集合,其实只是习惯说法,因为它是Collection接口的一个子接口(Collection有很多的子接口,这是其中三个主要的子接口之一,另外两个后面都会说到),所以Collection接口中定义的方法在List接口中也是可以使用的,另外还根据List的特点,又引入了其他的方法。
List接口的特点:
元素是以一种线性方式进行存储的元素存取有序,即元素的存入顺序和取出顺序一致。元素带有索引,通过索引就可以精确的操作集合中的元素(与数组类似)元素可以重复,通过元素的equals方法,来比较是否为重复的元素
2.List的使用
2.1List的常用方法
基本介绍:
这里说的常用方法是指除了实现Collection接口之外的。前面说到List集合中的元素是可以通过索引来操作集合中的元素的,所以List 集合里添加了一些根据索引来操作集合元素的方法。下面对这些方法进行简单
介绍:
void add(iint index, E element): 在列表中指定的位置上插入指定的元素boolean addAll(int index, Collection c): 将指定的集合中的所有元素插入到指定位置的列表中E get(int index):返回此列表中指定位置的元素List subList(int fromIndex, int toIndex):返回List中一部分对象的集合,即返回的集合是List的子集合,并是以下标索引取值。父集合List以fromIndex开始(包含),到toIndex结束(不包含)的 部分为返回的子集合int indexOf(Object obj):返回此列表中指定元素的第一个出现的索引,如果此列表不包含元素,返回- 1int lastIndexOf(Object obj):返回此列表中指定元素的最后一个发生的索引,如果此列表不包含元素,返回- 1E remove(int index):移除此列表中指定位置的元素E set(int index, E element):用指定元素替换此列表中指定位置的元素
代码示例:
public class ListDemo {
public static void main(String[] args) {
// 通过List的实现类ArrayList创建List集合对象
List
// 指定位置添加元素
list.add(0,"jack");
list.add(1,"rose");
list.add(2,"marry");
System.out.println(list);
// 删除索引位置为2的元素
list.remove(2);
System.out.println(list);
// 指定元素替换此列表中指定位置的元素
list.set(0, "老王");
System.out.println(list);
// 获取指定位置元素(也遍历输出下)
for(int i = 0;i System.out.println(list.get(i)); } //还可以使用增强for for (String string : list) { System.out.println(string); } } } 3.List的实现类 作为一个接口,List的实现类才是我们创建对象时候使用的(上面代码示例里面用到了ArrayList实现类)。在List接口里,有三个常用的实现类:ArrayList、Vector、LinkedList。下面从源码中分析和介绍它们。 3.1ArrayList ArrayList底层通过数组实现,ArrayList可以随着元素的增加而动态扩容。它是一个数组队列,是java集合框架中使用最多的一个类,但是它是线程不安全的。 特点:以数组的形式进行存储,因此随机访问速度较快,所有它适用于查询缺点:不适用于插入和删除的操作 因为每次操作都需要移动数组中的元素;线程不安全 下面看下ArrayList的源码: public class ArrayList implements List /** * Default initial capacity. 初始化的时候如果没有指定长度的话,使用默认长度10 */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. 空数组 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. 空数组 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * Constructs an empty list with an initial capacity of ten.构造一个初始容量为10 */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//初始化为空数组 } public boolean add(E e) { //查看当前数组是否够多存一个元素 ensureCapacityInternal(size + 1); // Increments modCount!! //存入新元素到[size]位置,然后size自增1 elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果当前数组还是空数组 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //那么minCapacity取DEFAULT_CAPACITY与minCapacity的最大值 return Math.max(DEFAULT_CAPACITY, minCapacity); } //查看是否需要扩容 return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++;//修改次数加1 // 如果需要的最小容量比当前数组的长度大,即当前数组不够存,就扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length;//当前数组容量 int newCapacity = oldCapacity + (oldCapacity >> 1);//新数组容量是旧数组容量的1.5倍 //看旧数组的1.5倍是否够 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //看旧数组的1.5倍是否超过最大数组限制 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); //复制一个新数组 elementData = Arrays.copyOf(elementData, newCapacity); } public boolean remove(Object o) { //先找到o在当前ArrayList的数组中的下标 //分o是否为空两种情况讨论 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) {//null值用==比较 fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) {//非null值用equals比较 fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++;//修改次数加1 //需要移动的元素个数 int numMoved = size - index - 1; //如果需要移动元素,就用System.arraycopy移动元素 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //将elementData[size-1]位置置空,让GC回收空间,元素个数减少 elementData[--size] = null; // clear to let GC do its work } public E remove(int index) { rangeCheck(index);//检验index是否合法 modCount++;//修改次数加1 //取出[index]位置的元素,[index]位置的元素就是要被删除的元素,用于最后返回被删除的元素 E oldValue = elementData(index); //需要移动的元素个数 int numMoved = size - index - 1; //如果需要移动元素,就用System.arraycopy移动元素 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //将elementData[size-1]位置置空,让GC回收空间,元素个数减少 elementData[--size] = null; // clear to let GC do its work return oldValue; } public E set(int index, E element) { rangeCheck(index);//检验index是否合法 //取出[index]位置的元素,[index]位置的元素就是要被替换的元素,用于最后返回被替换的元素 E oldValue = elementData(index); //用element替换[index]位置的元素 elementData[index] = element; return oldValue; } public E get(int index) { rangeCheck(index);//检验index是否合法 return elementData(index);//返回[index]位置的元素 } public int indexOf(Object o) { //分为o是否为空两种情况 if (o == null) { //从前往后找 for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } public int lastIndexOf(Object o) { //分为o是否为空两种情况 if (o == null) { //从后往前找 for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } 从上面的源码中我们可以看到: ArrayList 在初始化的时候如果我们没有指定长度的话,它会有一个默认长度10,每次扩容的时候为增加1.5倍然后是ArrayList 的一些常见的方法的源码介绍 3.2Vector Vector的底层也是通过数组实现,方法与ArrayList基本一致,。但是Vector是线程安全的. 这是因为其加上了 synchronized 关键字, 用来保证线程安全。 优点: 以数组的形式进行存储,因此随机访问速度较快,所有它适用于查询;线程安全缺点: 不适用于插入和删除的操作 因为每次操作都需要移动数组中的元素 下面看下Vector的源码: /** * Constructs an empty vector so that its internal data array * has size {@code 10} and its standard capacity increment is * zero. */ public Vector() { this(10); //指定初始容量initialCapacity为10 } public Vector(int initialCapacity) { this(initialCapacity, 0);//指定capacityIncrement增量为0 } public Vector(int initialCapacity, int capacityIncrement增量为0) { super(); //判断了形参初始容量initialCapacity的合法性 if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //创建了一个Object[]类型的数组 this.elementData = new Object[initialCapacity];//默认是10 //增量,默认是0,如果是0,后面就按照2倍增加,如果不是0,后面就按照你指定的增量进行增量 this.capacityIncrement = capacityIncrement; } //synchronized意味着线程安全的 public synchronized boolean add(E e) { modCount++; //看是否需要扩容 ensureCapacityHelper(elementCount + 1); //把新的元素存入[elementCount],存入后,elementCount元素的个数增1 elementData[elementCount++] = e; return true; } private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code //看是否超过了当前数组的容量 if (minCapacity - elementData.length > 0) grow(minCapacity);//扩容 } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length;//获取目前数组的长度 //如果capacityIncrement增量是0,新容量 = oldCapacity的2倍 //如果capacityIncrement增量是不是0,新容量 = oldCapacity + capacityIncrement增量; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //如果按照上面计算的新容量还不够,就按照你指定的需要的最小容量来扩容minCapacity if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //如果新容量超过了最大数组限制,那么单独处理 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); //把旧数组中的数据复制到新数组中,新数组的长度为newCapacity elementData = Arrays.copyOf(elementData, newCapacity); } public boolean remove(Object o) { return removeElement(o); } public synchronized boolean removeElement(Object obj) { modCount++; //查找obj在当前Vector中的下标 int i = indexOf(obj); //如果i>=0,说明存在,删除[i]位置的元素 if (i >= 0) { removeElementAt(i); return true; } return false; } public int indexOf(Object o) { return indexOf(o, 0); } public synchronized int indexOf(Object o, int index) { if (o == null) {//要查找的元素是null值 for (int i = index ; i < elementCount ; i++) if (elementData[i]==null)//如果是null值,用==null判断 return i; } else {//要查找的元素是非null值 for (int i = index ; i < elementCount ; i++) if (o.equals(elementData[i]))//如果是非null值,用equals判断 return i; } return -1; } public synchronized void removeElementAt(int index) { modCount++; //判断下标的合法性 if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); } //j是要移动的元素的个数 int j = elementCount - index - 1; //如果需要移动元素,就调用System.arraycopy进行移动 if (j > 0) { //把index+1位置以及后面的元素往前移动 //index+1的位置的元素移动到index位置,依次类推 //一共移动j个 System.arraycopy(elementData, index + 1, elementData, index, j); } //元素的总个数减少 elementCount--; //将elementData[elementCount]这个位置置空,用来添加新元素,位置的元素等着被GC回收 elementData[elementCount] = null; /* to let gc do its work */ } 从上面的源码中我们可以看到: Vector在初始化的时候如果我们没有指定长度的话,它会有一个默认长度10,每次扩容的时候为增加2倍然后是Vector的一些常见的方法的源码介绍 3.3LinkedList LinkedList底层的数据存储结构是链表结构,而且还是一个双向链表,可以实现双向操作。此外,LinkedList还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用,如peek 、push、pop等方法。 优点: 以链表形式进行存储,因此随机访问速度查询慢,增删快。缺点: 线程不安全 下面看一下源码: int size = 0; Node Node private static class Node E item;//元素数据 Node Node Node(Node this.item = element; this.next = next; this.prev = prev; } } public boolean add(E e) { linkLast(e);//默认把新元素链接到链表尾部 return true; } void linkLast(E e) { final Node //创建新结点 final Node //现在的新结点是最后一个结点了 last = newNode; //如果l==null,说明原来的链表是空的 if (l == null) //那么新结点同时也是第一个结点 first = newNode; else //否则把新结点链接到原来的最后一个结点的next中 l.next = newNode; //元素个数增加 size++; //修改次数增加 modCount++; } public boolean remove(Object o) { //分o是否为空两种情况 if (o == null) { pVrzFu//找到o对应的结点x for (Node if (x.item == null) { unlink(x);//删除x结点 return true; } } } else { //找到o对应的结点x for (Node if (o.equals(x.item)) { unlink(x);//删除x结点 return true; } } } return false; } E unlink(Node // assert x != null; final E element = x.item;//被删除结点的数据 final Node final Node //如果被删除结点的前面没有结点,说明被删除结点是第一个结点 if (prev == null) { //那么被删除结点的下一个结点变为第一个结点 first = next; } else {//被删除结点不是第一个结点 //被删除结点的上一个结点的next指向被删除结点的下一个结点 prev.next = next; //断开被删除结点与上一个结点的链接 x.prev = null;//使得GC回收 } //如果被删除结点的后面没有结点,说明被删除结点是最后一个结点 if (next == null) { //那么被删除结点的上一个结点变为最后一个结点 last = prev; } else {//被删除结点不是最后一个结点 //被删除结点的下一个结点的prev执行被删除结点的上一个结点 next.prev = prev; //断开被删除结点与下一个结点的连接 x.next = null;//使得GC回收 } //把被删除结点的数据也置空,使得GC回收 x.item = null; //元素个数减少 size--; //修改次数增加 modCount++; //返回被删除结点的数据 return element; } 从上面的源码中我们可以看到: LinkedList是基于链表的,所以没有扩容方法,默认加入元素是尾部自动扩容然后是LinkedList的一些常见的方法的源码介绍 3.4ArrayList与Vector的区别 它们的底层结构都是数组,我们称为动态数组。 ArrayList是新版的动态数组,线程不安全,效率高,Vector是旧版的动态数组,线程安全,效率低。动态数组的扩容机制不同,ArrayList扩容为原来的1.5倍,Vector扩容增加为原来的2倍。数组的初始化容量,如果在构建ArrayList与Vector的集合对象时,没有显式指定初始化容量,那么Vector的内部数组的初始容量默认为10,而ArrayList在JDK1.6及之前的版本也是10,而JDK1.7之后的版本ArrayList初始化为长度为0的空数组,之后在添加第一个元素时,再创建长度为10的数组。
System.out.println(list.get(i));
}
//还可以使用增强for
for (String string : list) {
System.out.println(string);
}
}
}
3.List的实现类
作为一个接口,List的实现类才是我们创建对象时候使用的(上面代码示例里面用到了ArrayList实现类)。在List接口里,有三个常用的实现类:ArrayList、Vector、LinkedList。下面从源码中分析和介绍它们。
3.1ArrayList
ArrayList底层通过数组实现,ArrayList可以随着元素的增加而动态扩容。它是一个数组队列,是java集合框架中使用最多的一个类,但是它是线程不安全的。
特点:以数组的形式进行存储,因此随机访问速度较快,所有它适用于查询缺点:不适用于插入和删除的操作 因为每次操作都需要移动数组中的元素;线程不安全
下面看下ArrayList的源码:
public class ArrayList
implements List
/**
* Default initial capacity. 初始化的时候如果没有指定长度的话,使用默认长度10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances. 空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added. 空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* Constructs an empty list with an initial capacity of ten.构造一个初始容量为10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//初始化为空数组
}
public boolean add(E e) {
//查看当前数组是否够多存一个元素
ensureCapacityInternal(size + 1); // Increments modCount!!
//存入新元素到[size]位置,然后size自增1
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果当前数组还是空数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//那么minCapacity取DEFAULT_CAPACITY与minCapacity的最大值
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//查看是否需要扩容
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//修改次数加1
// 如果需要的最小容量比当前数组的长度大,即当前数组不够存,就扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//当前数组容量
int newCapacity = oldCapacity + (oldCapacity >> 1);//新数组容量是旧数组容量的1.5倍
//看旧数组的1.5倍是否够
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//看旧数组的1.5倍是否超过最大数组限制
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//复制一个新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
public boolean remove(Object o) {
//先找到o在当前ArrayList的数组中的下标
//分o是否为空两种情况讨论
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {//null值用==比较
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {//非null值用equals比较
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;//修改次数加1
//需要移动的元素个数
int numMoved = size - index - 1;
//如果需要移动元素,就用System.arraycopy移动元素
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将elementData[size-1]位置置空,让GC回收空间,元素个数减少
elementData[--size] = null; // clear to let GC do its work
}
public E remove(int index) {
rangeCheck(index);//检验index是否合法
modCount++;//修改次数加1
//取出[index]位置的元素,[index]位置的元素就是要被删除的元素,用于最后返回被删除的元素
E oldValue = elementData(index);
//需要移动的元素个数
int numMoved = size - index - 1;
//如果需要移动元素,就用System.arraycopy移动元素
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将elementData[size-1]位置置空,让GC回收空间,元素个数减少
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
public E set(int index, E element) {
rangeCheck(index);//检验index是否合法
//取出[index]位置的元素,[index]位置的元素就是要被替换的元素,用于最后返回被替换的元素
E oldValue = elementData(index);
//用element替换[index]位置的元素
elementData[index] = element;
return oldValue;
}
public E get(int index) {
rangeCheck(index);//检验index是否合法
return elementData(index);//返回[index]位置的元素
}
public int indexOf(Object o) {
//分为o是否为空两种情况
if (o == null) {
//从前往后找
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
public int lastIndexOf(Object o) {
//分为o是否为空两种情况
if (o == null) {
//从后往前找
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
从上面的源码中我们可以看到:
ArrayList 在初始化的时候如果我们没有指定长度的话,它会有一个默认长度10,每次扩容的时候为增加1.5倍然后是ArrayList 的一些常见的方法的源码介绍
3.2Vector
Vector的底层也是通过数组实现,方法与ArrayList基本一致,。但是Vector是线程安全的. 这是因为其加上了 synchronized 关键字, 用来保证线程安全。
优点: 以数组的形式进行存储,因此随机访问速度较快,所有它适用于查询;线程安全缺点: 不适用于插入和删除的操作 因为每次操作都需要移动数组中的元素
下面看下Vector的源码:
/**
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*/
public Vector() {
this(10); //指定初始容量initialCapacity为10
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);//指定capacityIncrement增量为0
}
public Vector(int initialCapacity, int capacityIncrement增量为0) {
super();
//判断了形参初始容量initialCapacity的合法性
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//创建了一个Object[]类型的数组
this.elementData = new Object[initialCapacity];//默认是10
//增量,默认是0,如果是0,后面就按照2倍增加,如果不是0,后面就按照你指定的增量进行增量
this.capacityIncrement = capacityIncrement;
}
//synchronized意味着线程安全的
public synchronized boolean add(E e) {
modCount++;
//看是否需要扩容
ensureCapacityHelper(elementCount + 1);
//把新的元素存入[elementCount],存入后,elementCount元素的个数增1
elementData[elementCount++] = e;
return true;
}
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
//看是否超过了当前数组的容量
if (minCapacity - elementData.length > 0)
grow(minCapacity);//扩容
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//获取目前数组的长度
//如果capacityIncrement增量是0,新容量 = oldCapacity的2倍
//如果capacityIncrement增量是不是0,新容量 = oldCapacity + capacityIncrement增量;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//如果按照上面计算的新容量还不够,就按照你指定的需要的最小容量来扩容minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新容量超过了最大数组限制,那么单独处理
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//把旧数组中的数据复制到新数组中,新数组的长度为newCapacity
elementData = Arrays.copyOf(elementData, newCapacity);
}
public boolean remove(Object o) {
return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
modCount++;
//查找obj在当前Vector中的下标
int i = indexOf(obj);
//如果i>=0,说明存在,删除[i]位置的元素
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
public int indexOf(Object o) {
return indexOf(o, 0);
}
public synchronized int indexOf(Object o, int index) {
if (o == null) {//要查找的元素是null值
for (int i = index ; i < elementCount ; i++)
if (elementData[i]==null)//如果是null值,用==null判断
return i;
} else {//要查找的元素是非null值
for (int i = index ; i < elementCount ; i++)
if (o.equals(elementData[i]))//如果是非null值,用equals判断
return i;
}
return -1;
}
public synchronized void removeElementAt(int index) {
modCount++;
//判断下标的合法性
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
//j是要移动的元素的个数
int j = elementCount - index - 1;
//如果需要移动元素,就调用System.arraycopy进行移动
if (j > 0) {
//把index+1位置以及后面的元素往前移动
//index+1的位置的元素移动到index位置,依次类推
//一共移动j个
System.arraycopy(elementData, index + 1, elementData, index, j);
}
//元素的总个数减少
elementCount--;
//将elementData[elementCount]这个位置置空,用来添加新元素,位置的元素等着被GC回收
elementData[elementCount] = null; /* to let gc do its work */
}
从上面的源码中我们可以看到:
Vector在初始化的时候如果我们没有指定长度的话,它会有一个默认长度10,每次扩容的时候为增加2倍然后是Vector的一些常见的方法的源码介绍
3.3LinkedList
LinkedList底层的数据存储结构是链表结构,而且还是一个双向链表,可以实现双向操作。此外,LinkedList还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用,如peek 、push、pop等方法。
优点: 以链表形式进行存储,因此随机访问速度查询慢,增删快。缺点: 线程不安全
下面看一下源码:
int size = 0;
Node
Node
private static class Node
E item;//元素数据
Node
Node
Node(Node
this.item = element;
this.next = next;
this.prev = prev;
}
}
public boolean add(E e) {
linkLast(e);//默认把新元素链接到链表尾部
return true;
}
void linkLast(E e) {
final Node
//创建新结点
final Node
//现在的新结点是最后一个结点了
last = newNode;
//如果l==null,说明原来的链表是空的
if (l == null)
//那么新结点同时也是第一个结点
first = newNode;
else
//否则把新结点链接到原来的最后一个结点的next中
l.next = newNode;
//元素个数增加
size++;
//修改次数增加
modCount++;
}
public boolean remove(Object o) {
//分o是否为空两种情况
if (o == null) {
pVrzFu//找到o对应的结点x
for (Node
if (x.item == null) {
unlink(x);//删除x结点
return true;
}
}
} else {
//找到o对应的结点x
for (Node
if (o.equals(x.item)) {
unlink(x);//删除x结点
return true;
}
}
}
return false;
}
E unlink(Node
// assert x != null;
final E element = x.item;//被删除结点的数据
final Node
final Node
//如果被删除结点的前面没有结点,说明被删除结点是第一个结点
if (prev == null) {
//那么被删除结点的下一个结点变为第一个结点
first = next;
} else {//被删除结点不是第一个结点
//被删除结点的上一个结点的next指向被删除结点的下一个结点
prev.next = next;
//断开被删除结点与上一个结点的链接
x.prev = null;//使得GC回收
}
//如果被删除结点的后面没有结点,说明被删除结点是最后一个结点
if (next == null) {
//那么被删除结点的上一个结点变为最后一个结点
last = prev;
} else {//被删除结点不是最后一个结点
//被删除结点的下一个结点的prev执行被删除结点的上一个结点
next.prev = prev;
//断开被删除结点与下一个结点的连接
x.next = null;//使得GC回收
}
//把被删除结点的数据也置空,使得GC回收
x.item = null;
//元素个数减少
size--;
//修改次数增加
modCount++;
//返回被删除结点的数据
return element;
}
从上面的源码中我们可以看到:
LinkedList是基于链表的,所以没有扩容方法,默认加入元素是尾部自动扩容然后是LinkedList的一些常见的方法的源码介绍
3.4ArrayList与Vector的区别
它们的底层结构都是数组,我们称为动态数组。
ArrayList是新版的动态数组,线程不安全,效率高,Vector是旧版的动态数组,线程安全,效率低。动态数组的扩容机制不同,ArrayList扩容为原来的1.5倍,Vector扩容增加为原来的2倍。数组的初始化容量,如果在构建ArrayList与Vector的集合对象时,没有显式指定初始化容量,那么Vector的内部数组的初始容量默认为10,而ArrayList在JDK1.6及之前的版本也是10,而JDK1.7之后的版本ArrayList初始化为长度为0的空数组,之后在添加第一个元素时,再创建长度为10的数组。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~