Java集合源码剖析(一)【集合框架概述、ArrayList、LinkedList、Vector】

关于ArrayList的源码,给出几点比较重要的总结:

1、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为10,带有Collection参数的构造方法,将Collection转化为数组赋给ArrayList的实现数组elementData。

2、注意扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍加1,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容量),而后用Arrays.copyof()方法将元素拷贝到新的数组(详见下面的第3点)。从中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。

3、ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。我们有必要对这两个方法的实现做下深入的了解。

首先来看Arrays.copyof()方法。它有很多个重载的方法,但实现思路都是一样的,我们来看泛型版本的源码:

[java]  view plain copy 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. public static  T[] copyOf(T[] original, int newLength) {

  2. return (T[]) copyOf(original, newLength, original.getClass());

  3. }

很明显调用了另一个copyof方法,该方法有三个参数,最后一个参数指明要转换的数据的类型,其源码如下:

[java]  view plain copy 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {

  2. T[] copy = ((Object)newType == (Object)Object[].class)

  3. ? (T[]) new Object[newLength]

  4. : (T[]) Array.newInstance(newType.getComponentType(), newLength);

  5. System.arraycopy(original, 0, copy, 0,

  6. Math.min(original.length, newLength));

  7. return copy;

  8. }

这里可以很明显地看出,该方法实际上是在其内部又创建了一个长度为newlength的数组,调用System.arraycopy()方法,将原来数组中的元素复制到了新的数组中。

下面来看System.arraycopy()方法。该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。

4、注意ArrayList的两个转化为静态数组的toArray方法。

第一个,Object[] toArray()方法。该方法有可能会抛出java.lang.ClassCastException异常,如果直接用向下转型的方法,将整个ArrayList集合转变为指定类型的Array数组,便会抛出该异常,而如果转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该异常,显然对数组中的元素一个个进行向下转型,效率不高,且不太方便。

第二个, T[] toArray(T[] a)方法。该方法可以直接将ArrayList转换得到的Array进行整体向下转型(转型其实是在该方法的源码中实现的),且从该方法的源码中可以看出,参数a的大小不足时,内部会调用Arrays.copyOf方法,该方法内部创建一个新的数组返回,因此对该方法的常用形式如下:

[java]  view plain copy 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. public static Integer[] vectorToArray2(ArrayList v) {

  2. Integer[] newText = (Integer[])v.toArray(new Integer[0]);

  3. return newText;

  4. }

5、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。

6、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。

LinkedList源码剖析

LinkedList简介

LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈、队列和双端队列来使用。

LinkedList同样是非线程安全的,只在单线程下适合使用。

LinkedList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了Cloneable接口,能被克隆。

LinkedList源码剖析

======================

LinkedList的源码如下(加入了比较详细的注释):

[java]  view plain copy 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. package java.util;

  2. public class LinkedList

  3. extends AbstractSequentialList

  4. implements List, Deque, Cloneable, java.io.Serializable

  5. {

  6. // 链表的表头,表头不包含任何数据。Entry是个链表类数据结构。

  7. private transient Entry header = new Entry(null, null, null);

  8. // LinkedList中元素个数

  9. private transient int size = 0;

  10. // 默认构造函数:创建一个空的链表

  11. public LinkedList() {

  12. header.next = header.previous = header;

  13. }

  14. // 包含“集合”的构造函数:创建一个包含“集合”的LinkedList

  15. public LinkedList(Collection<? extends E> c) {

  16. this();

  17. addAll©;

  18. }

  19. // 获取LinkedList的第一个元素

  20. public E getFirst() {

  21. if (size==0)

  22. throw new NoSuchElementException();

  23. // 链表的表头header中不包含数据。

  24. // 这里返回header所指下一个节点所包含的数据。

  25. return header.next.element;

  26. }

  27. // 获取LinkedList的最后一个元素

  28. public E getLast()  {

  29. if (size==0)

  30. throw new NoSuchElementException();

  31. // 由于LinkedList是双向链表;而表头header不包含数据。

  32. // 因而,这里返回表头header的前一个节点所包含的数据。

  33. return header.previous.element;

  34. }

  35. // 删除LinkedList的第一个元素

  36. public E removeFirst() {

  37. return remove(header.next);

  38. }

  39. // 删除LinkedList的最后一个元素

  40. public E removeLast() {

  41. return remove(header.previous);

  42. }

  43. // 将元素添加到LinkedList的起始位置

  44. public void addFirst(E e) {

  45. addBefore(e, header.next);

  46. }

  47. // 将元素添加到LinkedList的结束位置

  48. public void addLast(E e) {

  49. addBefore(e, header);

  50. }

  51. // 判断LinkedList是否包含元素(o)

  52. public boolean contains(Object o) {

  53. return indexOf(o) != -1;

  54. }

  55. // 返回LinkedList的大小

  56. public int size() {

  57. return size;

  58. }

  59. // 将元素(E)添加到LinkedList中

  60. public boolean add(E e) {

  61. // 将节点(节点数据是e)添加到表头(header)之前。

  62. // 即,将节点添加到双向链表的末端。

  63. addBefore(e, header);

  64. return true;

  65. }

  66. // 从LinkedList中删除元素(o)

  67. // 从链表开始查找,如存在元素(o)则删除该元素并返回true;

  68. // 否则,返回false。

  69. public boolean remove(Object o) {

  70. if (o==null) {

  71. // 若o为null的删除情况

  72. for (Entry e = header.next; e != header; e = e.next) {

  73. if (e.element==null) {

  74. remove(e);

  75. return true;

  76. }

  77. }

  78. } else {

  79. // 若o不为null的删除情况

  80. for (Entry e = header.next; e != header; e = e.next) {

  81. if (o.equals(e.element)) {

  82. remove(e);

  83. return true;

  84. }

  85. }

  86. }

  87. return false;

  88. }

  89. // 将“集合©”添加到LinkedList中。

  90. // 实际上,是从双向链表的末尾开始,将“集合©”添加到双向链表中。

  91. public boolean addAll(Collection<? extends E> c) {

  92. return addAll(size, c);

  93. }

  94. // 从双向链表的index开始,将“集合©”添加到双向链表中。

  95. public boolean addAll(int index, Collection<? extends E> c) {

  96. if (index < 0 || index > size)

  97. throw new IndexOutOfBoundsException("Index: "+index+

  98. ", Size: "+size);

  99. Object[] a = c.toArray();

  100. // 获取集合的长度

  101. int numNew = a.length;

  102. if (numNew==0)

  103. return false;

  104. modCount++;

  105. // 设置“当前要插入节点的后一个节点”

  106. Entry successor = (index==size ? header : entry(index));

  107. // 设置“当前要插入节点的前一个节点”

  108. Entry predecessor = successor.previous;

  109. // 将集合©全部插入双向链表中

  110. for (int i=0; i<numNew; i++) {

  111. Entry e = new Entry((E)a[i], successor, predecessor);

  112. predecessor.next = e;

  113. predecessor = e;

  114. }

  115. successor.previous = predecessor;

  116. // 调整LinkedList的实际大小

  117. size += numNew;

  118. return true;

  119. }

  120. // 清空双向链表

  121. public void clear() {

  122. Entry e = header.next;

  123. // 从表头开始,逐个向后遍历;对遍历到的节点执行一下操作:

  124. // (01) 设置前一个节点为null

  125. // (02) 设置当前节点的内容为null

  126. // (03) 设置后一个节点为“新的当前节点”

  127. while (e != header) {

  128. Entry next = e.next;

  129. e.next = e.previous = null;

  130. e.element = null;

  131. e = next;

  132. }

  133. header.next = header.previous = header;

  134. // 设置大小为0

  135. size = 0;

  136. modCount++;

  137. }

  138. // 返回LinkedList指定位置的元素

  139. public E get(int index) {

  140. return entry(index).element;

  141. }

  142. // 设置index位置对应的节点的值为element

  143. public E set(int index, E element) {

  144. Entry e = entry(index);

  145. E oldVal = e.element;

  146. e.element = element;

  147. return oldVal;

  148. }

  149. // 在index前添加节点,且节点的值为element

  150. public void add(int index, E element) {

  151. addBefore(element, (index==size ? header : entry(index)));

  152. }

  153. // 删除index位置的节点

  154. public E remove(int index) {

  155. return remove(entry(index));

  156. }

  157. // 获取双向链表中指定位置的节点

  158. private Entry entry(int index) {

  159. if (index < 0 || index >= size)

  160. throw new IndexOutOfBoundsException("Index: "+index+

  161. ", Size: "+size);

  162. Entry e = header;

  163. // 获取index处的节点。

  164. // 若index < 双向链表长度的1/2,则从前先后查找;

  165. // 否则,从后向前查找。

  166. if (index < (size >> 1)) {

  167. for (int i = 0; i <= index; i++)

  168. e = e.next;

  169. } else {

  170. for (int i = size; i > index; i–)

  171. e = e.previous;

  172. }

  173. return e;

  174. }

  175. // 从前向后查找,返回“值为对象(o)的节点对应的索引”

  176. // 不存在就返回-1

  177. public int indexOf(Object o) {

  178. int index = 0;

  179. if (o==null) {

  180. for (Entry e = header.next; e != header; e = e.next) {

  181. if (e.element==null)

  182. return index;

  183. index++;

  184. }

  185. } else {

  186. for (Entry e = header.next; e != header; e = e.next) {

  187. if (o.equals(e.element))

  188. return index;

  189. index++;

  190. }

  191. }

  192. return -1;

  193. }

  194. // 从后向前查找,返回“值为对象(o)的节点对应的索引”

  195. // 不存在就返回-1

  196. public int lastIndexOf(Object o) {

  197. int index = size;

  198. if (o==null) {

  199. for (Entry e = header.previous; e != header; e = e.previous) {

  200. index–;

  201. if (e.element==null)

  202. return index;

  203. }

  204. } else {

  205. for (Entry e = header.previous; e != header; e = e.previous) {

  206. index–;

  207. if (o.equals(e.element))

  208. return index;

  209. }

  210. }

  211. return -1;

  212. }

  213. // 返回第一个节点

  214. // 若LinkedList的大小为0,则返回null

  215. public E peek() {

  216. if (size==0)

  217. return null;

  218. return getFirst();

  219. }

  220. // 返回第一个节点

  221. // 若LinkedList的大小为0,则抛出异常

  222. public E element() {

  223. return getFirst();

  224. }

  225. // 删除并返回第一个节点

  226. // 若LinkedList的大小为0,则返回null

  227. public E poll() {

  228. if (size==0)

  229. return null;

  230. return removeFirst();

  231. }

  232. // 将e添加双向链表末尾

  233. public boolean offer(E e) {

  234. return add(e);

  235. }

  236. // 将e添加双向链表开头

  237. public boolean offerFirst(E e) {

  238. addFirst(e);

  239. return true;

  240. }

  241. // 将e添加双向链表末尾

  242. public boolean offerLast(E e) {

  243. addLast(e);

  244. return true;

  245. }

  246. // 返回第一个节点

  247. // 若LinkedList的大小为0,则返回null

  248. public E peekFirst() {

  249. if (size==0)

  250. return null;

  251. return getFirst();

  252. }

  253. // 返回最后一个节点

  254. // 若LinkedList的大小为0,则返回null

  255. public E peekLast() {

  256. if (size==0)

  257. return null;

  258. return getLast();

  259. }

  260. // 删除并返回第一个节点

  261. // 若LinkedList的大小为0,则返回null

  262. public E pollFirst() {

  263. if (size==0)

  264. return null;

  265. return removeFirst();

  266. }

  267. // 删除并返回最后一个节点

  268. // 若LinkedList的大小为0,则返回null

  269. public E pollLast() {

  270. if (size==0)

  271. return null;

  272. return removeLast();

  273. }

  274. // 将e插入到双向链表开头

  275. public void push(E e) {

  276. addFirst(e);

  277. }

  278. // 删除并返回第一个节点

  279. public E pop() {

  280. return removeFirst();

  281. }

  282. // 从LinkedList开始向后查找,删除第一个值为元素(o)的节点

  283. // 从链表开始查找,如存在节点的值为元素(o)的节点,则删除该节点

  284. public boolean removeFirstOccurrence(Object o) {

  285. return remove(o);

  286. }

  287. // 从LinkedList末尾向前查找,删除第一个值为元素(o)的节点

  288. // 从链表开始查找,如存在节点的值为元素(o)的节点,则删除该节点

  289. public boolean removeLastOccurrence(Object o) {

  290. if (o==null) {

  291. for (Entry e = header.previous; e != header; e = e.previous) {

  292. if (e.element==null) {

  293. remove(e);

  294. return true;

  295. }

  296. }

  297. } else {

  298. for (Entry e = header.previous; e != header; e = e.previous) {

  299. if (o.equals(e.element)) {

  300. remove(e);

  301. return true;

  302. }

  303. }

  304. }

  305. return false;

  306. }

  307. // 返回“index到末尾的全部节点”对应的ListIterator对象(List迭代器)

  308. public ListIterator listIterator(int index) {

  309. return new ListItr(index);

  310. }

  311. // List迭代器

  312. private class ListItr implements ListIterator {

  313. // 上一次返回的节点

  314. private Entry lastReturned = header;

  315. // 下一个节点

  316. private Entry next;

  317. // 下一个节点对应的索引值

  318. private int nextIndex;

  319. // 期望的改变计数。用来实现fail-fast机制。

  320. private int expectedModCount = modCount;

  321. // 构造函数。

  322. // 从index位置开始进行迭代

  323. ListItr(int index) {

  324. // index的有效性处理

  325. if (index < 0 || index > size)

  326. throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size);

  327. // 若 “index 小于 ‘双向链表长度的一半’”,则从第一个元素开始往后查找;

  328. // 否则,从最后一个元素往前查找。

  329. if (index < (size >> 1)) {

  330. next = header.next;

  331. for (nextIndex=0; nextIndex<index; nextIndex++)

  332. next = next.next;

  333. } else {

  334. next = header;

  335. for (nextIndex=size; nextIndex>index; nextIndex–)

  336. next = next.previous;

  337. }

  338. }

  339. // 是否存在下一个元素

  340. public boolean hasNext() {

  341. // 通过元素索引是否等于“双向链表大小”来判断是否达到最后。

  342. return nextIndex != size;

  343. }

  344. // 获取下一个元素

  345. public E next() {

  346. checkForComodification();

  347. if (nextIndex == size)

  348. throw new NoSuchElementException();

  349. lastReturned = next;

  350. // next指向链表的下一个元素

  351. next = next.next;

  352. nextIndex++;

  353. return lastReturned.element;

  354. }

  355. // 是否存在上一个元素

  356. public boolean hasPrevious() {

  357. // 通过元素索引是否等于0,来判断是否达到开头。

  358. return nextIndex != 0;

  359. }

  360. // 获取上一个元素

  361. public E previous() {

  362. if (nextIndex == 0)

  363. throw new NoSuchElementException();

  364. // next指向链表的上一个元素

  365. lastReturned = next = next.previous;

  366. nextIndex–;

  367. checkForComodification();

  368. return lastReturned.element;

  369. }

  370. // 获取下一个元素的索引

  371. public int nextIndex() {

  372. return nextIndex;

  373. }

  374. // 获取上一个元素的索引

  375. public int previousIndex() {

  376. return nextIndex-1;

  377. }

  378. // 删除当前元素。

  379. // 删除双向链表中的当前节点

  380. public void remove() {

  381. checkForComodification();

  382. Entry lastNext = lastReturned.next;

  383. try {

  384. LinkedList.this.remove(lastReturned);

  385. } catch (NoSuchElementException e) {

  386. throw new IllegalStateException();

  387. }

  388. if (next==lastReturned)

  389. next = lastNext;

  390. else

  391. nextIndex–;

  392. lastReturned = header;

  393. expectedModCount++;

  394. }

  395. // 设置当前节点为e

  396. public void set(E e) {

  397. if (lastReturned == header)

  398. throw new IllegalStateException();

  399. checkForComodification();

  400. lastReturned.element = e;

  401. }

  402. // 将e添加到当前节点的前面

  403. public void add(E e) {

  404. checkForComodification();

  405. lastReturned = header;

  406. addBefore(e, next);

  407. nextIndex++;

  408. expectedModCount++;

  409. }

  410. // 判断 “modCount和expectedModCount是否相等”,依次来实现fail-fast机制。

  411. final void checkForComodification() {

  412. if (modCount != expectedModCount)

  413. throw new ConcurrentModificationException();

  414. }

  415. }

  416. // 双向链表的节点所对应的数据结构。

  417. // 包含3部分:上一节点,下一节点,当前节点值。

  418. private static class Entry {

  419. // 当前节点所包含的值

  420. E element;

  421. // 下一个节点

  422. Entry next;

  423. // 上一个节点

  424. Entry previous;

  425. /**

  426. * 链表节点的构造函数。

  427. * 参数说明:

  428. *   element  —— 节点所包含的数据

  429. *   next      —— 下一个节点

  430. *   previous —— 上一个节点

  431. */

  432. Entry(E element, Entry next, Entry previous) {

  433. this.element = element;

  434. this.next = next;

  435. this.previous = previous;

  436. }

  437. }

  438. // 将节点(节点数据是e)添加到entry节点之前。

  439. private Entry addBefore(E e, Entry entry) {

  440. // 新建节点newEntry,将newEntry插入到节点e之前;并且设置newEntry的数据是e

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

  442. newEntry.previous.next = newEntry;

  443. newEntry.next.previous = newEntry;

  444. // 修改LinkedList大小

  445. size++;

  446. // 修改LinkedList的修改统计数:用来实现fail-fast机制。

  447. modCount++;

  448. return newEntry;

  449. }

  450. // 将节点从链表中删除

  451. private E remove(Entry e) {

  452. if (e == header)

  453. throw new NoSuchElementException();

  454. E result = e.element;

  455. e.previous.next = e.next;

  456. e.next.previous = e.previous;

  457. e.next = e.previous = null;

  458. e.element = null;

  459. size–;

  460. modCount++;

  461. return result;

  462. }

  463. // 反向迭代器

  464. public Iterator descendingIterator() {

  465. return new DescendingIterator();

  466. }

  467. // 反向迭代器实现类。

  468. private class DescendingIterator implements Iterator {

  469. final ListItr itr = new ListItr(size());

  470. // 反向迭代器是否下一个元素。

  471. // 实际上是判断双向链表的当前节点是否达到开头

  472. public boolean hasNext() {

  473. return itr.hasPrevious();

  474. }

  475. // 反向迭代器获取下一个元素。

  476. // 实际上是获取双向链表的前一个节点

  477. public E next() {

  478. return itr.previous();

  479. }

  480. // 删除当前节点

  481. public void remove() {

  482. itr.remove();

  483. }

  484. }

  485. // 返回LinkedList的Object[]数组

  486. public Object[] toArray() {

  487. // 新建Object[]数组

  488. Object[] result = new Object[size];

  489. int i = 0;

  490. // 将链表中所有节点的数据都添加到Object[]数组中

  491. for (Entry e = header.next; e != header; e = e.next)

  492. result[i++] = e.element;

  493. return result;

  494. }

  495. // 返回LinkedList的模板数组。所谓模板数组,即可以将T设为任意的数据类型

  496. public  T[] toArray(T[] a) {

  497. // 若数组a的大小 < LinkedList的元素个数(意味着数组a不能容纳LinkedList中全部元素)

  498. // 则新建一个T[]数组,T[]的大小为LinkedList大小,并将该T[]赋值给a。

  499. if (a.length < size)

  500. a = (T[])java.lang.reflect.Array.newInstance(

  501. a.getClass().getComponentType(), size);

  502. // 将链表中所有节点的数据都添加到数组a中

  503. int i = 0;

  504. Object[] result = a;

  505. for (Entry e = header.next; e != header; e = e.next)

  506. result[i++] = e.element;

  507. if (a.length > size)

  508. a[size] = null;

  509. return a;

  510. }

  511. // 克隆函数。返回LinkedList的克隆对象。

  512. public Object clone() {

  513. LinkedList clone = null;

  514. // 克隆一个LinkedList克隆对象

  515. try {

  516. clone = (LinkedList) super.clone();

  517. } catch (CloneNotSupportedException e) {

  518. throw new InternalError();

  519. }

  520. // 新建LinkedList表头节点

  521. clone.header = new Entry(null, null, null);

  522. clone.header.next = clone.header.previous = clone.header;

  523. clone.size = 0;

  524. clone.modCount = 0;

  525. // 将链表中所有节点的数据都添加到克隆对象中

  526. for (Entry e = header.next; e != header; e = e.next)

  527. clone.add(e.element);

  528. return clone;

  529. }

  530. // java.io.Serializable的写入函数

  531. // 将LinkedList的“容量,所有的元素值”都写入到输出流中

  532. private void writeObject(java.io.ObjectOutputStream s)

  533. throws java.io.IOException {

  534. // Write out any hidden serialization magic

  535. s.defaultWriteObject();

  536. // 写入“容量”

  537. s.writeInt(size);

  538. // 将链表中所有节点的数据都写入到输出流中

  539. for (Entry e = header.next; e != header; e = e.next)

  540. s.writeObject(e.element);

  541. }

  542. // java.io.Serializable的读取函数:根据写入方式反向读出

  543. // 先将LinkedList的“容量”读出,然后将“所有的元素值”读出

  544. private void readObject(java.io.ObjectInputStream s)

  545. throws java.io.IOException, ClassNotFoundException {

  546. // Read in any hidden serialization magic

  547. s.defaultReadObject();

  548. // 从输入流中读取“容量”

  549. int size = s.readInt();

  550. // 新建链表表头节点

  551. header = new Entry(null, null, null);

  552. header.next = header.previous = header;

  553. // 从输入流中将“所有的元素值”并逐个添加到链表中

  554. for (int i=0; i<size; i++)

  555. addBefore((E)s.readObject(), header);

  556. }

  557. }

几点总结

关于LinkedList的源码,给出几点比较重要的总结:

1、从源码中很明显可以看出,LinkedList的实现是基于双向循环链表的,且头结点中不存放数据,如下图;

2、注意两个不同的构造方法。无参构造方法直接建立一个仅包含head节点的空链表,包含Collection的构造方法,先调用无参构造方法建立一个空链表,而后将Collection中的数据加入到链表的尾部后面。

3、在查找和删除某元素时,源码中都划分为该元素为null和不为null两种情况来处理,LinkedList中允许元素为null。

4、LinkedList是基于链表实现的,因此不存在容量不足的问题,所以这里没有扩容的方法。

5、注意源码中的Entry entry(int index)方法。该方法返回双向链表中指定位置处的节点,而链表中是没有下标索引的,要指定位置出的元素,就要遍历该链表,从源码的实现中,我们看到这里有一个加速动作。源码中先将index与长度size的一半比较,如果index<size/2,就只从位置0往后遍历到位置index处,而如果index>size/2,就只从位置size往前遍历到位置index处。这样可以减少一部分不必要的遍历,从而提高一定的效率(实际上效率还是很低)。

6、注意链表类对应的数据结构Entry。如下;

[java]  view plain copy 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. // 双向链表的节点所对应的数据结构。

  2. // 包含3部分:上一节点,下一节点,当前节点值。

  3. private static class Entry {

  4. // 当前节点所包含的值

  5. E element;

  6. // 下一个节点

  7. Entry next;

  8. // 上一个节点

  9. Entry previous;

  10. /**

  11. * 链表节点的构造函数。

  12. * 参数说明:

  13. *   element  —— 节点所包含的数据

  14. *   next      —— 下一个节点

  15. *   previous —— 上一个节点

  16. */

  17. Entry(E element, Entry next, Entry previous) {

  18. this.element = element;

  19. this.next = next;

  20. this.previous = previous;

  21. }

  22. }

7、LinkedList是基于链表实现的,因此插入删除效率高,查找效率低(虽然有一个加速动作)。

8、要注意源码中还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用。

Vector源码剖析

Vector简介

Vector也是基于数组实现的,是一个动态数组,其容量能自动增长。

Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是相对安全,有些时候还是要加入同步语句来保证线程的安全),可以用于多线程环境。

Vector没有丝线Serializable接口,因此它不支持序列化,实现了Cloneable接口,能被克隆,实现了RandomAccess接口,支持快速随机访问。

Vector源码剖析

==================

Vector的源码如下(加入了比较详细的注释):

[java]  view plain copy

  1. package java.util;

  2. public class Vector

  3. extends AbstractList

  4. implements List, RandomAccess, Cloneable, java.io.Serializable

  5. {

  6. // 保存Vector中数据的数组

  7. protected Object[] elementData;

  8. // 实际数据的数量

  9. protected int elementCount;

  10. // 容量增长系数

  11. protected int capacityIncrement;

  12. // Vector的序列版本号

  13. private static final long serialVersionUID = -2767605614048989439L;

  14. // Vector构造函数。默认容量是10。

  15. public Vector() {

  16. this(10);

  17. }

  18. // 指定Vector容量大小的构造函数

  19. public Vector(int initialCapacity) {

  20. this(initialCapacity, 0);

  21. }

  22. // 指定Vector"容量大小"和"增长系数"的构造函数

  23. public Vector(int initialCapacity, int capacityIncrement) {

  24. super();

  25. if (initialCapacity < 0)

  26. throw new IllegalArgumentException("Illegal Capacity: "+

  27. initialCapacity);

  28. // 新建一个数组,数组容量是initialCapacity

  29. this.elementData = new Object[initialCapacity];

  30. // 设置容量增长系数

  31. this.capacityIncrement = capacityIncrement;

  32. }

  33. // 指定集合的Vector构造函数。

  34. public Vector(Collection<? extends E> c) {

  35. // 获取“集合©”的数组,并将其赋值给elementData

  36. elementData = c.toArray();

  37. // 设置数组长度

  38. elementCount = elementData.length;

  39. // c.toArray might (incorrectly) not return Object[] (see 6260652)

  40. if (elementData.getClass() != Object[].class)

  41. elementData = Arrays.copyOf(elementData, elementCount, Object[].class);

  42. }

  43. // 将数组Vector的全部元素都拷贝到数组anArray中

  44. public synchronized void copyInto(Object[] anArray) {

  45. System.arraycopy(elementData, 0, anArray, 0, elementCount);

  46. }

  47. // 将当前容量值设为 =实际元素个数

  48. public synchronized void trimToSize() {

  49. modCount++;

  50. int oldCapacity = elementData.length;

  51. if (elementCount < oldCapacity) {

  52. elementData = Arrays.copyOf(elementData, elementCount);

  53. }

  54. }

  55. // 确认“Vector容量”的帮助函数

  56. private void ensureCapacityHelper(int minCapacity) {

  57. int oldCapacity = elementData.length;

  58. // 当Vector的容量不足以容纳当前的全部元素,增加容量大小。

  59. // 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement

  60. // 否则,将容量增大一倍。

  61. if (minCapacity > oldCapacity) {

  62. Object[] oldData = elementData;

  63. int newCapacity = (capacityIncrement > 0) ?

  64. (oldCapacity + capacityIncrement) : (oldCapacity * 2);

  65. if (newCapacity < minCapacity) {

  66. newCapacity = minCapacity;

  67. }

  68. elementData = Arrays.copyOf(elementData, newCapacity);

  69. }

  70. }

  71. // 确定Vector的容量。

  72. public synchronized void ensureCapacity(int minCapacity) {

  73. // 将Vector的改变统计数+1

  74. modCount++;

  75. ensureCapacityHelper(minCapacity);

  76. }

  77. // 设置容量值为 newSize

  78. public synchronized void setSize(int newSize) {

  79. modCount++;

  80. if (newSize > elementCount) {

  81. // 若 “newSize 大于 Vector容量”,则调整Vector的大小。

  82. ensureCapacityHelper(newSize);

  83. } else {

  84. // 若 “newSize 小于/等于 Vector容量”,则将newSize位置开始的元素都设置为null

  85. for (int i = newSize ; i < elementCount ; i++) {

  86. elementData[i] = null;

  87. }

  88. }

  89. elementCount = newSize;

  90. }

  91. // 返回“Vector的总的容量”

  92. public synchronized int capacity() {

  93. return elementData.length;

  94. }

  95. // 返回“Vector的实际大小”,即Vector中元素个数

  96. public synchronized int size() {

  97. return elementCount;

  98. }

  99. // 判断Vector是否为空

  100. public synchronized boolean isEmpty() {

  101. return elementCount == 0;

  102. }

  103. // 返回“Vector中全部元素对应的Enumeration”

  104. public Enumeration elements() {

  105. // 通过匿名类实现Enumeration

  106. return new Enumeration() {

  107. int count = 0;

  108. // 是否存在下一个元素

  109. public boolean hasMoreElements() {

  110. return count < elementCount;

  111. }

  112. // 获取下一个元素

  113. public E nextElement() {

  114. synchronized (Vector.this) {

  115. if (count < elementCount) {

  116. return (E)elementData[count++];

  117. }

  118. }

  119. throw new NoSuchElementException(“Vector Enumeration”);

  120. }

  121. };

  122. }

  123. // 返回Vector中是否包含对象(o)

  124. public boolean contains(Object o) {

  125. return indexOf(o, 0) >= 0;

  126. }

  127. // 从index位置开始向后查找元素(o)。

  128. // 若找到,则返回元素的索引值;否则,返回-1

  129. public synchronized int indexOf(Object o, int index) {

  130. if (o == null) {

  131. // 若查找元素为null,则正向找出null元素,并返回它对应的序号

  132. for (int i = index ; i < elementCount ; i++)

  133. if (elementData[i]==null)

  134. return i;

  135. } else {

  136. // 若查找元素不为null,则正向找出该元素,并返回它对应的序号

  137. for (int i = index ; i < elementCount ; i++)

  138. if (o.equals(elementData[i]))

  139. return i;

  140. }

  141. return -1;

  142. }

  143. // 查找并返回元素(o)在Vector中的索引值

  144. public int indexOf(Object o) {

  145. return indexOf(o, 0);

  146. }

  147. // 从后向前查找元素(o)。并返回元素的索引

  148. public synchronized int lastIndexOf(Object o) {

  149. return lastIndexOf(o, elementCount-1);

  150. }

  151. // 从后向前查找元素(o)。开始位置是从前向后的第index个数;

  152. // 若找到,则返回元素的“索引值”;否则,返回-1。

  153. public synchronized int lastIndexOf(Object o, int index) {

  154. if (index >= elementCount)

  155. throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

  156. if (o == null) {

  157. // 若查找元素为null,则反向找出null元素,并返回它对应的序号

  158. for (int i = index; i >= 0; i–)

  159. if (elementData[i]==null)

  160. return i;

  161. } else {

  162. // 若查找元素不为null,则反向找出该元素,并返回它对应的序号

  163. for (int i = index; i >= 0; i–)

  164. if (o.equals(elementData[i]))

  165. return i;

  166. }

  167. return -1;

  168. }

  169. // 返回Vector中index位置的元素。

  170. // 若index月结,则抛出异常

  171. public synchronized E elementAt(int index) {

  172. if (index >= elementCount) {

  173. throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);

  174. }

  175. return (E)elementData[index];

  176. }

  177. // 获取Vector中的第一个元素。

  178. // 若失败,则抛出异常!

  179. public synchronized E firstElement() {

  180. if (elementCount == 0) {

  181. throw new NoSuchElementException();

  182. }

  183. return (E)elementData[0];

  184. }

  185. // 获取Vector中的最后一个元素。

  186. // 若失败,则抛出异常!

  187. public synchronized E lastElement() {

  188. if (elementCount == 0) {

  189. throw new NoSuchElementException();

  190. }

  191. return (E)elementData[elementCount - 1];

  192. }

  193. // 设置index位置的元素值为obj

  194. public synchronized void setElementAt(E obj, int index) {

  195. if (index >= elementCount) {

  196. throw new ArrayIndexOutOfBoundsException(index + " >= " +

  197. elementCount);

  198. }

  199. elementData[index] = obj;

  200. }

  201. // 删除index位置的元素

  202. public synchronized void removeElementAt(int index) {

  203. modCount++;

  204. if (index >= elementCount) {

  205. throw new ArrayIndexOutOfBoundsException(index + " >= " +

  206. elementCount);

  207. } else if (index < 0) {

  208. throw new ArrayIndexOutOfBoundsException(index);

  209. }

  210. int j = elementCount - index - 1;

  211. if (j > 0) {

  212. System.arraycopy(elementData, index + 1, elementData, index, j);

  213. }

  214. elementCount–;

  215. elementData[elementCount] = null; /* to let gc do its work */

  216. }

  217. // 在index位置处插入元素(obj)

  218. public synchronized void insertElementAt(E obj, int index) {

  219. modCount++;

  220. if (index > elementCount) {

  221. throw new ArrayIndexOutOfBoundsException(index

  222. + " > " + elementCount);

  223. }

  224. ensureCapacityHelper(elementCount + 1);

  225. System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);

  226. elementData[index] = obj;

  227. elementCount++;

  228. }

  229. // 将“元素obj”添加到Vector末尾

  230. public synchronized void addElement(E obj) {

  231. modCount++;

  232. ensureCapacityHelper(elementCount + 1);

  233. elementData[elementCount++] = obj;

  234. }

  235. // 在Vector中查找并删除元素obj。

  236. // 成功的话,返回true;否则,返回false。

  237. public synchronized boolean removeElement(Object obj) {

  238. modCount++;

  239. int i = indexOf(obj);

  240. if (i >= 0) {

  241. removeElementAt(i);

  242. return true;

  243. }

  244. return false;

  245. }

  246. // 删除Vector中的全部元素

  247. public synchronized void removeAllElements() {

  248. modCount++;

  249. // 将Vector中的全部元素设为null

  250. for (int i = 0; i < elementCount; i++)

  251. elementData[i] = null;

  252. elementCount = 0;

  253. }

  254. // 克隆函数

  255. public synchronized Object clone() {

  256. try {

  257. Vector v = (Vector) super.clone();

  258. // 将当前Vector的全部元素拷贝到v中

  259. v.elementData = Arrays.copyOf(elementData, elementCount);

  260. v.modCount = 0;

  261. return v;

  262. } catch (CloneNotSupportedException e) {

  263. // this shouldn’t happen, since we are Cloneable

  264. throw new InternalError();

  265. }

  266. }

  267. // 返回Object数组

  268. public synchronized Object[] toArray() {

  269. return Arrays.copyOf(elementData, elementCount);

  270. }

  271. // 返回Vector的模板数组。所谓模板数组,即可以将T设为任意的数据类型

  272. public synchronized  T[] toArray(T[] a) {

  273. // 若数组a的大小 < Vector的元素个数;

  274. // 则新建一个T[]数组,数组大小是“Vector的元素个数”,并将“Vector”全部拷贝到新数组中

  275. if (a.length < elementCount)

  276. return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

  277. // 若数组a的大小 >= Vector的元素个数;

  278. // 则将Vector的全部元素都拷贝到数组a中。

  279. System.arraycopy(elementData, 0, a, 0, elementCount);

  280. if (a.length > elementCount)

  281. a[elementCount] = null;

  282. return a;

  283. }

  284. // 获取index位置的元素

  285. public synchronized E get(int index) {

  286. if (index >= elementCount)

  287. throw new ArrayIndexOutOfBoundsException(index);

  288. return (E)elementData[index];

  289. }

  290. // 设置index位置的值为element。并返回index位置的原始值

  291. public synchronized E set(int index, E element) {

  292. if (index >= elementCount)

  293. throw new ArrayIndexOutOfBoundsException(index);

  294. Object oldValue = elementData[index];

  295. elementData[index] = element;

  296. return (E)oldValue;

  297. }

  298. // 将“元素e”添加到Vector最后。

  299. public synchronized boolean add(E e) {

  300. modCount++;

  301. ensureCapacityHelper(elementCount + 1);

  302. elementData[elementCount++] = e;

  303. return true;

  304. }

  305. // 删除Vector中的元素o

  306. public boolean remove(Object o) {

  307. return removeElement(o);

  308. }

  309. // 在index位置添加元素element

  310. public void add(int index, E element) {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
     return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

  1. // 若数组a的大小 >= Vector的元素个数;

  2. // 则将Vector的全部元素都拷贝到数组a中。

  3. System.arraycopy(elementData, 0, a, 0, elementCount);

  4. if (a.length > elementCount)

  5. a[elementCount] = null;

  6. return a;

  7. }

  8. // 获取index位置的元素

  9. public synchronized E get(int index) {

  10. if (index >= elementCount)

  11. throw new ArrayIndexOutOfBoundsException(index);

  12. return (E)elementData[index];

  13. }

  14. // 设置index位置的值为element。并返回index位置的原始值

  15. public synchronized E set(int index, E element) {

  16. if (index >= elementCount)

  17. throw new ArrayIndexOutOfBoundsException(index);

  18. Object oldValue = elementData[index];

  19. elementData[index] = element;

  20. return (E)oldValue;

  21. }

  22. // 将“元素e”添加到Vector最后。

  23. public synchronized boolean add(E e) {

  24. modCount++;

  25. ensureCapacityHelper(elementCount + 1);

  26. elementData[elementCount++] = e;

  27. return true;

  28. }

  29. // 删除Vector中的元素o

  30. public boolean remove(Object o) {

  31. return removeElement(o);

  32. }

  33. // 在index位置添加元素element

  34. public void add(int index, E element) {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-irkc8dzB-1715451645381)]

[外链图片转存中…(img-aioRkeLk-1715451645381)]

[外链图片转存中…(img-dyxDrFqx-1715451645381)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值