List笔录
List相较于set、map,是按照一定顺序存储,List主要分为3类,ArrayList, LinkedList和Vector。以下是List的结构图,本文章重点讲解ArrayList与LinkedList的底层实现原理。
ArrayList
ArrayList采用了快速失败的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。优点:随机访问元素
缺点:中间插入和移除元素速度较慢。定义:
[java] view plain copy print?
- public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 1.AbstractList提供了List接口的默认实现(个别方法为抽象方法)。2.List接口定义了列表必须实现的方法。
3.RandomAccess是一个标记接口,接口内没有定义任何内容。
4. 实现了Cloneable接口的类,可以调用Object.clone方法返回该对象的浅拷贝。
5. 通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。序列化接口没有方法或字段,仅用于标识可序列化的语义。
底层原理:1.底层使用数组实现
有两个私有属性:[java] view plain copy print?
- private transient Object[] elementData;
private transient Object[] elementData; (elementData存储内部元素,Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient)[java] view plain copy print?
- private int size;
private int size; (size存储元素数量)2.构造方法:
1.构造一个默认初始容量为10的空列表。[java] view plain copy print?
- public ArrayList() {
- this(10);
- }
public ArrayList() {
this(10);
} 2.构造一个指定初始容量的空列表
[java] view plain copy print?
- public ArrayList(int initialCapacity) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
- this.elementData = new Object[initialCapacity];
- }
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
3.构造一个包含指定collection的元素的列表,这些元素按照collection的迭代器返回它们的顺序排列。(返回若不是Object[]将调用Arrays.copyOf方法将其转为Object[])
[java] view plain copy print ?
- public ArrayList(Collection<? extends E> c) {
- elementData = c.toArray();
- size = elementData.length;
- // c.toArray might (incorrectly) not return Object[] (see 6260652)
- if (elementData.getClass() != Object[].class)
- elementData = Arrays.copyOf(elementData, size, Object[].class);
- }
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}3.存储:
ArrayList提供了set(int index, E element)、add(E e)、add(int index, E element)、addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c)这些添加元素的方法。
[java] view plain copy print?- public boolean add(E e) {
- ensureCapacity(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}看到add(E e)中先调用了ensureCapacity(size+1)方法,之后将元素的索引赋给elementData[size],而后size自增。例如初次添加时,size为0,add将elementData[0]赋值为e,然后size设置为1(类似执行以下两条语句elementData[0]=e;size=1)。将元素的索引赋给elementData[size]不是会出现数组越界的情况吗?这里关键就在ensureCapacity(size+1)中了。
[java]view plain copy print?
- public void ensureCapacity(int minCapacity) {
- modCount++;
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {
- Object oldData[] = elementData;
- int newCapacity = (oldCapacity * 3) / 2 + 1;
- if (newCapacity < minCapacity) {
- newCapacity = minCapacity;
- }
- // minCapacity is usually close to size, so this is a win:
- elementData = Arrays.copyOf(elementData, newCapacity);
- }
- }
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3) / 2 + 1;
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}[java] view plain copy print?
- // 将指定的元素插入此列表中的指定位置。
- // 如果当前位置有元素,则向右移动当前位于该位置的元素以及所有后续元素(将其索引加1)。
- public void add(int index, E element) {
- if (index > size || index < 0)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
- + size);
- // 如果数组长度不足,将进行扩容。
- ensureCapacity(size + 1); // Increments modCount!!
- // 将 elementData中从Index位置开始、长度为size-index的元素,
- // 拷贝到从下标为index+1位置开始的新的elementData数组中。
- // 即将当前位于该位置的元素以及所有后续元素右移一个位置。
- System.arraycopy(elementData, index, elementData, index + 1, size
- - index);
- elementData[index] = element;
- size++;
- }
// 将指定的元素插入此列表中的指定位置。
// 如果当前位置有元素,则向右移动当前位于该位置的元素以及所有后续元素(将其索引加1)。
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
// 如果数组长度不足,将进行扩容。
ensureCapacity(size + 1); // Increments modCount!!
// 将 elementData中从Index位置开始、长度为size-index的元素,
// 拷贝到从下标为index+1位置开始的新的elementData数组中。
// 即将当前位于该位置的元素以及所有后续元素右移一个位置。
System.arraycopy(elementData, index, elementData, index + 1, size
- index);
elementData[index] = element;
size++;
}[java] view plain copy print?
- public boolean addAll(Collection<? extends E> c) {
- Object[] a = c.toArray();
- int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
- System.arraycopy(a, 0, elementData, size, numNew);
- size += numNew;
- return numNew != 0;
- }
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}先将集合c转换成数组,根据转换后数组的程度和ArrayList的size拓展容量,之后调用System.arraycopy方法复制元素到elementData的尾部,调整size。根据返回的内容分析,只要集合c的大小不为空,即转换后的数组长度不为0则返回true。
[java] view plain copy print?
- public boolean addAll(int index, Collection<? extends E> c) {
- if (index > size || index < 0)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
- + size);
- Object[] a = c.toArray();
- int numNew = a.length;
- ensureCapacity(size + numNew); // Increments modCount
- int numMoved = size - index;
- if (numMoved > 0)
- System.arraycopy(elementData, index, elementData, index + numNew,
- numMoved);
- System.arraycopy(a, 0, elementData, index, numNew);
- size += numNew;
- return numNew != 0;
- }
public boolean addAll(int index, Collection<? extends E> c) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}先判断index是否越界。其他内容与addAll(Collection<? extends E> c)基本一致,只是复制的时候先将index开始的元素向后移动X(c转为数组后的长度)个位置(也是一个复制的过程),之后将数组内容复制到elementData的index位置至index+X。
[java] view plain copyprint?
- // 用指定的元素替代此列表中指定位置上的元素,并返回以前位于该位置上的元素。
- public E set(int index, E element) {
- RangeCheck(index);
- E oldValue = (E) elementData[index];
- elementData[index] = element;
- return oldValue;
- }
// 用指定的元素替代此列表中指定位置上的元素,并返回以前位于该位置上的元素。
public E set(int index, E element) {
RangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
} 4.读取
[java] view plain copy print?
- // 返回此列表中指定位置上的元素。
- public E get(int index) {
- RangeCheck(index);
- return (E) elementData[index];
- }
- private void RangeCheck(int index) {
- if (index >= size)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
- + size);
- }
// 返回此列表中指定位置上的元素。
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
}5.删除
[java] view plain copy print?- // 移除此列表中指定位置上的元素。
- public E remove(int index) {
- RangeCheck(index);
- modCount++;
- E oldValue = (E) elementData[index];
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index + 1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- return oldValue;
- }
- // 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。
- public boolean remove(Object o) {
- // 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。
- if (o == null) {
- for (int index = 0; index < size; index++) {
- if (elementData[index] == null) {
- // 类似remove(int index),移除列表中指定位置上的元素。
- fastRemove(index);
- return true;
- }
- }
- } else {
- for (int index = 0; index < size; index++) {
- if (o.equals(elementData[index])) {
- fastRemove(index);
- return true;
- }
- }
- }
- return false;
- }
// 移除此列表中指定位置上的元素。
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
// 移除此列表中首次出现的指定元素(如果存在)。这是应为ArrayList中允许存放重复的元素。
public boolean remove(Object o) {
// 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。
if (o == null) {
for (int index = 0; index < size; index++) {
if (elementData[index] == null) {
// 类似remove(int index),移除列表中指定位置上的元素。
fastRemove(index);
return true;
}
}
} else {
for (int index = 0; index < size; index++) {
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
}
return false;
}6.数据清除:
[java] view plain copy print?- public void clear() {
- modCount++;
- // Let gc do its work
- for (int i = 0; i < size; i++) {
- elementData[i] = null;
- }
- size = 0;
- }
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++) {
elementData[i] = null;
}
size = 0;
}7.数据复制:
[java] view plain copy print?- public Object clone() {
- try {
- ArrayList<E> v = (ArrayList<E>) super.clone();
- v.elementData = Arrays.copyOf(elementData, size);
- v.modCount = 0;
- return v;
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
- }
- }
public Object clone() {
try {
ArrayList<E> v = (ArrayList<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}8.查找数据是否存在:
[java] view plain copy print?- public boolean contains(Object o) {
- return indexOf(o) >= 0;
- }
public boolean contains(Object o) {
return indexOf(o) >= 0;
}9.查询数据坐标:
[java] view plain copy print?
- <span style="font-weight:normal;">public int indexOf(Object 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;
- }</span>
public int indexOf(Object 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;
}10.转化为数组:
[java] view plain copy print?- public Object[] toArray() {
- return Arrays.copyOf(elementData, size);
- }
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
11.
[java] view plain copy print?- public void trimToSize() {
- modCount++;
- int oldCapacity = elementData.length;
- if (size < oldCapacity) {
- elementData = Arrays.copyOf(elementData, size);
- }
- }
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}将elementData的数组设置为ArrayList实际的容量,动态增长的多余容量被删除了。
LinkedList
优点:中间插入和移除元素代价比较小,优化了顺序访问,在Queue或者栈中应用缺点:随机访问比较慢
定义:
[java] view plain copy print ?
- public class LinkedList<E>extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable1.LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。2.LinkedList 实现 List 接口,能对它进行队列操作。
3.LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
4.LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
5.LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
6.LinkedList 是非同步的。
底层原理:LinkedList底层的数据结构是基于双向循环链表的,且头结点中不存放数据
1.私有属性:
[java] view plain copy print?
- private transient Entry<E> header = new Entry<E>( null, null, null);
- private transient int size = 0;
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0;
以下是节点类Entry的实现:
[java] view plain copy print?- private static class Entry<E> {
- E element;
- Entry<E> next;
- Entry<E> previous;
- Entry(E element, Entry<E> next, Entry<E> previous) {
- this.element = element;
- this.next = next;
- this.previous = previous;
- }
- }
private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}next和previous分别表示该节点的下一个节点跟下一个节点。element是该节点包含的值
2.构造方法:
第一个无参构造方法:[java] view plain copy print?
- public LinkedList() {
- header.next = header.previous = header;
- }
public LinkedList() {
header.next = header.previous = header;
}第一个构造方法将header的next跟pervious都指向header,这就是一个双向循环链表的初始化;整个链表就是只有header一个结点,表现为空链表。
第二个接收一个Collection参数c:
[java] view plain copy print ?
- public LinkedList(Collection<? extends E> c) {
- this();
- addAll(c);
- }
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}先调用第一个构造方法,构造一个空的LinkedList,然后把c通过addAll方法加入进去。
3.增加元素
无论add的哪个实现都需要用到addBefore这个方法,这个方法是私有方法,无法直接从外部程序调用,若需要,只能通过反射。[java] view plain copy print?
- private Entry<E> addBefore(E e, Entry<E> entry) {
- Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
- newEntry.previous.next = newEntry;
- newEntry.next.previous = newEntry;
- size++;
- modCount++;
- return newEntry;
- }
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}[java] view plain copy print?
- // 将元素(E)添加到LinkedList中
- public boolean add(E e) {
- // 将节点(节点数据是e)添加到表头(header)之前。
- // 即,将节点添加到双向链表的末端。
- addBefore(e, header);
- return true;
- }
// 将元素(E)添加到LinkedList中
public boolean add(E e) {
// 将节点(节点数据是e)添加到表头(header)之前。
// 即,将节点添加到双向链表的末端。
addBefore(e, header);
return true;
}传入的是结点数据e,调用addBefore,首先在addBefore()方法内创建一个新的节点newEntry,使newEntry的上一个结点是header.previous,也就是尾部节点,因为这是一个双向循环链表,下一个节点是header,因为新加入的节点需要作为尾节点,作为双向循环链表,尾节点的下一个指向header。因为是双向的,所以需要让周围的节点指向newEntry,然后增加size;
以下的实际增加过程跟上述描述差不多,都是调用了addBefore()方法。
[java] view plain copy print?
- public void add(int index, E element) {
- addBefore(element, (index == size ? header : entry(index)));
- }
- public void addFirst(E e) {
- addBefore(e, header.next);
- }
- public void addLast(E e) {
- addBefore(e, header);
- }
public void add(int index, E element) {
addBefore(element, (index == size ? header : entry(index)));
}
public void addFirst(E e) {
addBefore(e, header.next);
}
public void addLast(E e) {
addBefore(e, header);
}4.删除数据:
[java] view plain copy print?- public E remove(int index) {
- Entry e = get(index);
- remove(e);
- return e.element;
- }
public E remove(int index) {
Entry e = get(index);
remove(e);
return e.element;
}调用了remove()方法,这个方法同样是私有方法,这就是双向链表删除节点的实现。
[java] view plain copy print?
- private void remove(E e) {
- if (e == header)
- throw new NoSuchElementException();
- // 将前一节点的next引用赋值为e的下一节点
- e.previous.next = e.next;
- // 将e的下一节点的previous赋值为e的上一节点
- e.next.previous = e.previous;
- // 上面两条语句的执行已经导致了无法在链表中访问到e节点,而下面解除了e节点对前后节点的引用
- e.next = e.previous = null;
- // 将被移除的节点的内容设为null
- e.element = null;
- // 修改size大小
- size--;
- }
private void remove(E e) {
if (e == header)
throw new NoSuchElementException();
// 将前一节点的next引用赋值为e的下一节点
e.previous.next = e.next;
// 将e的下一节点的previous赋值为e的上一节点
e.next.previous = e.previous;
// 上面两条语句的执行已经导致了无法在链表中访问到e节点,而下面解除了e节点对前后节点的引用
e.next = e.previous = null;
// 将被移除的节点的内容设为null
e.element = null;
// 修改size大小
size--;
}5.clear元素:
[java] view plain copy print?- public void clear() {
- Entry<E> e = header.next;
- // e可以理解为一个移动的“指针”,因为是循环链表,所以回到header的时候说明已经没有节点了
- while (e != header) {
- // 保留e的下一个节点的引用
- Entry<E> next = e.next;
- // 解除节点e对前后节点的引用
- e.next = e.previous = null;
- // 将节点e的内容置空
- e.element = null;
- // 将e移动到下一个节点
- e = next;
- }
- // 将header构造成一个循环链表,同构造方法构造一个空的LinkedList
- header.next = header.previous = header;
- // 修改size
- size = 0;
- modCount++;
- }
public void clear() {
Entry<E> e = header.next;
// e可以理解为一个移动的“指针”,因为是循环链表,所以回到header的时候说明已经没有节点了
while (e != header) {
// 保留e的下一个节点的引用
Entry<E> next = e.next;
// 解除节点e对前后节点的引用
e.next = e.previous = null;
// 将节点e的内容置空
e.element = null;
// 将e移动到下一个节点
e = next;
}
// 将header构造成一个循环链表,同构造方法构造一个空的LinkedList
header.next = header.previous = header;
// 修改size
size = 0;
modCount++;
}6.获取数据:
[java] view plain copy print?
- public E get(int index) {
- return entry(index).element;
- }
- // 获取双向链表中指定位置的节点
- private Entry<E> entry(int index) {
- if (index < 0 || index >= size)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
- + size);
- Entry<E> e = header;
- // 获取index处的节点。
- // 若index < 双向链表长度的1/2(位运算),则从前先后查找;
- // 否则,从后向前查找。
- if (index < (size >> 1)) {
- for (int i = 0; i <= index; i++)
- e = e.next;
- } else {
- for (int i = size; i > index; i--)
- e = e.previous;
- }
- return e;
- }
public E get(int index) {
return entry(index).element;
}
// 获取双向链表中指定位置的节点
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
Entry<E> e = header;
// 获取index处的节点。
// 若index < 双向链表长度的1/2(位运算),则从前先后查找;
// 否则,从后向前查找。
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
} 7.查询数据是否存在:
[java] view plain copy print?- public boolean contains(Object o) {
- return indexOf(o) != -1;
- }
- // 从前向后查找,返回“值为对象(o)的节点对应的索引” 不存在就返回-1
- public int indexOf(Object o) {
- int index = 0;
- if (o == null) {
- for (Entry e = header.next; e != header; e = e.next) {
- if (e.element == null)
- return index;
- index++;
- }
- } else {
- for (Entry e = header.next; e != header; e = e.next) {
- if (o.equals(e.element))
- return index;
- index++;
- }
- }
- return -1;
- }
public boolean contains(Object o) {
return indexOf(o) != -1;
}
// 从前向后查找,返回“值为对象(o)的节点对应的索引” 不存在就返回-1
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Entry e = header.next; e != header; e = e.next) {
if (e.element == null)
return index;
index++;
}
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}8.数据复制:
[java] view plain copy print?- public Object clone() {
- LinkedList<E> clone = null;
- try {
- clone = (LinkedList<E>) super.clone();
- } catch (CloneNotSupportedException e) {
- throw new InternalError();
- }
- clone.header = new Entry<E>(null, null, null);
- clone.header.next = clone.header.previous = clone.header;
- clone.size = 0;
- clone.modCount = 0;
- for (Entry<E> e = header.next; e != header; e = e.next)
- clone.add(e.element);
- return clone;
- }
public Object clone() {
LinkedList<E> clone = null;
try {
clone = (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
clone.header = new Entry<E>(null, null, null);
clone.header.next = clone.header.previous = clone.header;
clone.size = 0;
clone.modCount = 0;
for (Entry<E> e = header.next; e != header; e = e.next)
clone.add(e.element);
return clone;
}调用父类的clone()方法初始化对象链表clone,将clone构造成一个空的双向循环链表,之后将header的下一个节点开始将逐个节点添加到clone中。最后返回克隆的clone对象。
[java] view plain copy print ?
- public Object[] toArray() {
- Object[] result = new Object[size];
- int i = 0;
- for (Entry<E> e = header.next; e != header; e = e.next) {
- result[i++] = e.element;
- }
- return result;
- }
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Entry<E> e = header.next; e != header; e = e.next) {
result[i++] = e.element;
}
return result;
}[java] view plain copy print?
- public <T> T[] toArray(T[] a) {
- // 先判断出入的数组a的大小是否足够,若大小不够则拓展。
- // 这里用到了发射的方法,重新实例化了一个大小为size的数组。
- // 之后将数组a赋值给数组result,遍历链表向result中添加的元素。
- // 最后判断数组a的长度是否大于size,若大于则将size位置的内容设置为null。返回a*/
- if (a.length < size) {
- a = (T[]) java.lang.reflect.Array.newInstance(a.getClass()
- .getComponentType(), size);
- }
- int i = 0;
- Object[] result = a;
- for (Entry<E> e = header.next; e != header; e = e.next) {
- result[i++] = e.element;
- }
- if (a.length > size) {
- a[size] = null;
- }
- return a;
- }
public <T> T[] toArray(T[] a) {
// 先判断出入的数组a的大小是否足够,若大小不够则拓展。
// 这里用到了发射的方法,重新实例化了一个大小为size的数组。
// 之后将数组a赋值给数组result,遍历链表向result中添加的元素。
// 最后判断数组a的长度是否大于size,若大于则将size位置的内容设置为null。返回a*/
if (a.length < size) {
a = (T[]) java.lang.reflect.Array.newInstance(a.getClass()
.getComponentType(), size);
}
int i = 0;
Object[] result = a;
for (Entry<E> e = header.next; e != header; e = e.next) {
result[i++] = e.element;
}
if (a.length > size) {
a[size] = null;
}
return a;
}