上篇我们分析了ArrayList的底层实现,知道了ArrayList底层是基于数组实现的,因此具有查找修改快而插入删除慢的特点。本篇介绍的LinkedList是List接口的另一种实现,它的底层是基于双向链表实现的,因此它具有插入删除快而查找修改慢的特点,此外,通过对双向链表的操作还可以实现队列和栈的功能。LinkedList的底层结构如下图所示。

F表示头结点引用,L表示尾结点引用,链表的每个结点都有三个元素,分别是前继结点引用(P),结点元素的值(E),后继结点的引用(N)。结点由内部类Node表示,我们看看它的内部结构。

  1. //结点内部类
  2. private static class Node<E> {
  3. E item; //元素
  4. Node<E> next; //下一个节点
  5. Node<E> prev; //上一个节点
  6. Node(Node<E> prev, E element, Node<E> next) {
  7. this.item = element;
  8. this.next = next;
  9. this.prev = prev;
  10. }
  11. }

Node这个内部类其实很简单,只有三个成员变量和一个构造器,item表示结点的值,next为下一个结点的引用,prev为上一个结点的引用,通过构造器传入这三个值。接下来再看看LinkedList的成员变量和构造器。

  1. //集合元素个数
  2. transient int size = 0;
  3. //头结点引用
  4. transient Node<E> first;
  5. //尾节点引用
  6. transient Node<E> last;
  7. //无参构造器
  8. public LinkedList() {}
  9. //传入外部集合的构造器
  10. public LinkedList(Collection<? extends E> c) {
  11. this();
  12. addAll(c);
  13. }

LinkedList持有头结点的引用和尾结点的引用,它有两个构造器,一个是无参构造器,一个是传入外部集合的构造器。与ArrayList不同的是LinkedList没有指定初始大小的构造器。看看它的增删改查方法。

  1. //增(添加)
  2. public boolean add(E e) {
  3. //在链表尾部添加
  4. linkLast(e);
  5. return true;
  6. }
  7. //增(插入)
  8. public void add(int index, E element) {
  9. //判定index位置的合法性,index >= 0 && index <= size才可以
  10. checkPositionIndex(index);
  11. //如果插入的index等于size,则表示index是最后一个
  12. if (index == size) {
  13. //在链表尾部添加
  14. linkLast(element);
  15. } else {
  16. //在链表中部插入
  17. //传入的参数为当前的值element和index处的节点node(index)
  18. linkBefore(element, node(index));
  19. }
  20. }
  21. //删(给定下标)
  22. public E remove(int index) {
  23. //检查下标是否合法,index >= 0 && index <= size才可以
  24. checkElementIndex(index);
  25. //unlink方法的参数是index处的节点
  26. return unlink(node(index));
  27. }
  28. //删(给定元素)
  29. public boolean remove(Object o) {
  30. if (o == null) {
  31. //遍历整个链表删除
  32. for (Node<E> x = first; x != null; x = x.next) {
  33. if (x.item == null) {
  34. unlink(x);
  35. return true;
  36. }
  37. }
  38. } else {
  39. //遍历整个链表删除
  40. for (Node<E> x = first; x != null; x = x.next) {
  41. if (o.equals(x.item)) {
  42. //找到了就删除
  43. unlink(x);
  44. return true;
  45. }
  46. }
  47. }
  48. return false;
  49. }
  50. //改
  51. public E set(int index, E element) {
  52. //检查下标是否合法
  53. checkElementIndex(index);
  54. //获取指定下标的结点引用
  55. Node<E> x = node(index);
  56. //获取指定下标结点的值
  57. E oldVal = x.item;
  58. //将结点元素设置为新的值
  59. x.item = element;
  60. //返回之前的值
  61. return oldVal;
  62. }
  63. //查
  64. public E get(int index) {
  65. //检查下标是否合法
  66. checkElementIndex(index);
  67. //返回指定下标的结点的值
  68. return node(index).item;
  69. }

插入节点的具体方法

  1. //链接到指定结点之前
  2. void linkBefore(E e, Node<E> succ) {
  3. //获取给定结点的上一个结点引用
  4. final Node<E> pred = succ.prev;
  5. //创建新结点, 新结点的上一个结点引用指向给定结点的上一个结点
  6. //新结点的下一个结点的引用指向给定的结点
  7. final Node<E> newNode = new Node<>(pred, e, succ);
  8. //将给定结点的上一个结点引用指向新结点
  9. succ.prev = newNode;
  10. //如果给定结点的上一个结点为空, 表明给定结点为头结点
  11. if (pred == null) {
  12. //将头结点引用指向新结点
  13. first = newNode;
  14. } else {
  15. //否则, 将给定结点的上一个结点的下一个结点引用指向新结点
  16. pred.next = newNode;
  17. }
  18. //集合元素个数加一
  19. size++;
  20. //修改次数加一
  21. modCount++;
  22. }
  23. //卸载指定结点
  24. E unlink(Node<E> x) {
  25. //获取给定结点的元素
  26. final E element = x.item;
  27. //获取给定结点的下一个结点的引用
  28. final Node<E> next = x.next;
  29. //获取给定结点的上一个结点的引用
  30. final Node<E> prev = x.prev;
  31. //如果给定结点的上一个结点为空, 说明给定结点为头结点
  32. if (prev == null) {
  33. //将头结点引用指向给定结点的下一个结点
  34. first = next;
  35. } else {
  36. //将上一个结点的后继结点引用指向给定结点的后继结点
  37. prev.next = next;
  38. //将给定结点的上一个结点置空
  39. x.prev = null;
  40. }
  41. //如果给定结点的下一个结点为空, 说明给定结点为尾结点
  42. if (next == null) {
  43. //将尾结点引用指向给定结点的上一个结点
  44. last = prev;
  45. } else {
  46. //将下一个结点的前继结点引用指向给定结点的前继结点
  47. next.prev = prev;
  48. x.next = null;
  49. }
  50. //将给定结点的元素置空
  51. x.item = null;
  52. //集合元素个数减一
  53. size--;
  54. //修改次数加一
  55. modCount++;
  56. return element;
  57. }

linkBefore和unlink是具有代表性的链接结点和卸载结点的操作,其他的链接和卸载两端结点的方法与此类似,所以我们重点介绍linkBefore和unlink方法。

linkBefore方法的过程图:

unlink方法的过程图:

通过上面图示看到对链表的插入和删除操作的时间复杂度都是O(1),而对链表的查找和修改操作都需要遍历链表进行元素的定位,这两个操作都是调用的node(int index)方法定位元素,看看它是怎样通过下标来定位元素的。

  1. //根据指定位置获取结点
  2. Node<E> node(int index) {
  3. //如果下标在链表前半部分, 就从头开始查起.size >> 1值为size/2
  4. if (index < (size >> 1)) {
  5. Node<E> x = first;
  6. for (int i = 0; i < index; i++) {
  7. x = x.next;
  8. }
  9. return x;
  10. } else {
  11. //如果下标在链表后半部分, 就从尾开始查起
  12. Node<E> x = last;
  13. for (int i = size - 1; i > index; i--) {
  14. x = x.prev;
  15. }
  16. return x;
  17. }
  18. }

通过下标定位时先判断是在链表的上半部分还是下半部分,如果是在上半部分就从头开始找起,如果是下半部分就从尾开始找起,因此通过下标的查找和修改操作的时间复杂度是O(n/2)。通过对双向链表的操作还可以实现单项队列,双向队列和栈的功能。

单向队列操作:

  1. //获取头结点
  2. public E peek() {
  3. final Node<E> f = first;
  4. return (f == null) ? null : f.item;
  5. }
  6. //获取头结点
  7. public E element() {
  8. return getFirst();
  9. }
  10. //弹出头结点
  11. public E poll() {
  12. final Node<E> f = first;
  13. return (f == null) ? null : unlinkFirst(f);
  14. }
  15. //移除头结点
  16. public E remove() {
  17. return removeFirst();
  18. }
  19. //在队列尾部添加结点
  20. public boolean offer(E e) {
  21. return add(e);
  22. }

双向队列操作:

  1. //在头部添加
  2. public boolean offerFirst(E e) {
  3. addFirst(e);
  4. return true;
  5. }
  6. //在尾部添加
  7. public boolean offerLast(E e) {
  8. addLast(e);
  9. return true;
  10. }
  11. //获取头结点
  12. public E peekFirst() {
  13. final Node<E> f = first;
  14. return (f == null) ? null : f.item;
  15. }
  16. //获取尾结点
  17. public E peekLast() {
  18. final Node<E> l = last;
  19. return (l == null) ? null : l.item;
  20. }

栈操作:

  1. //入栈
  2. public void push(E e) {
  3. addFirst(e);
  4. }
  5. //出栈
  6. public E pop() {
  7. return removeFirst();
  8. }

不管是单向队列还是双向队列还是栈,其实都是对链表的头结点和尾结点进行操作,它们的实现都是基于addFirst(),addLast(),removeFirst(),removeLast()这四个方法,它们的操作和linkBefore()和unlink()类似,只不过一个是对链表两端操作,一个是对链表中间操作。可以说这四个方法都是linkBefore()和unlink()方法的特殊情况,因此不难理解它们的内部实现,在此不多做介绍。

到这里,我们对LinkedList的分析也即将结束,对全文中的重点做个总结:

  1. 1. LinkedList是基于双向链表实现的,不论是增删改查方法还是队列和栈的实现,都可通过操作结点实现
  2. 2. LinkedList无需提前指定容量,因为基于链表操作,集合的容量随着元素的加入自动增加
  3. 3. LinkedList删除元素后集合占用的内存自动缩小,无需像ArrayList一样调用trimToSize()方法
  4. 4. LinkedList的所有方法没有进行同步,因此它也不是线程安全的,应该避免在多线程环境下使用
  5. 5. 以上分析基于JDK1.8,其他版本会有些出入,因此不能一概而论

LinkedList源码JDK1.8

  1. /*
  2. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  3. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. *
  5. *
  6. *
  7. *
  8. *
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *
  15. *
  16. *
  17. *
  18. *
  19. *
  20. *
  21. *
  22. *
  23. *
  24. */
  25. package java.util;
  26. import java.util.function.Consumer;
  27. /**
  28. * Doubly-linked list implementation of the {@code List} and {@code Deque}
  29. * interfaces. Implements all optional list operations, and permits all
  30. * elements (including {@code null}).
  31. *
  32. * <p>All of the operations perform as could be expected for a doubly-linked
  33. * list. Operations that index into the list will traverse the list from
  34. * the beginning or the end, whichever is closer to the specified index.
  35. *
  36. * <p><strong>Note that this implementation is not synchronized.</strong>
  37. * If multiple threads access a linked list concurrently, and at least
  38. * one of the threads modifies the list structurally, it <i>must</i> be
  39. * synchronized externally. (A structural modification is any operation
  40. * that adds or deletes one or more elements; merely setting the value of
  41. * an element is not a structural modification.) This is typically
  42. * accomplished by synchronizing on some object that naturally
  43. * encapsulates the list.
  44. *
  45. * If no such object exists, the list should be "wrapped" using the
  46. * {@link Collections#synchronizedList Collections.synchronizedList}
  47. * method. This is best done at creation time, to prevent accidental
  48. * unsynchronized access to the list:<pre>
  49. * List list = Collections.synchronizedList(new LinkedList(...));</pre>
  50. *
  51. * <p>The iterators returned by this class's {@code iterator} and
  52. * {@code listIterator} methods are <i>fail-fast</i>: if the list is
  53. * structurally modified at any time after the iterator is created, in
  54. * any way except through the Iterator's own {@code remove} or
  55. * {@code add} methods, the iterator will throw a {@link
  56. * ConcurrentModificationException}. Thus, in the face of concurrent
  57. * modification, the iterator fails quickly and cleanly, rather than
  58. * risking arbitrary, non-deterministic behavior at an undetermined
  59. * time in the future.
  60. *
  61. * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  62. * as it is, generally speaking, impossible to make any hard guarantees in the
  63. * presence of unsynchronized concurrent modification. Fail-fast iterators
  64. * throw {@code ConcurrentModificationException} on a best-effort basis.
  65. * Therefore, it would be wrong to write a program that depended on this
  66. * exception for its correctness: <i>the fail-fast behavior of iterators
  67. * should be used only to detect bugs.</i>
  68. *
  69. * <p>This class is a member of the
  70. * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  71. * Java Collections Framework</a>.
  72. *
  73. * @author Josh Bloch
  74. * @see List
  75. * @see ArrayList
  76. * @since 1.2
  77. * @param <E> the type of elements held in this collection
  78. */
  79. public class LinkedList<E>
  80. extends AbstractSequentialList<E>
  81. implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  82. {
  83. transient int size = 0;
  84. /**
  85. * Pointer to first node.
  86. * Invariant: (first == null && last == null) ||
  87. * (first.prev == null && first.item != null)
  88. */
  89. transient Node<E> first;
  90. /**
  91. * Pointer to last node.
  92. * Invariant: (first == null && last == null) ||
  93. * (last.next == null && last.item != null)
  94. */
  95. transient Node<E> last;
  96. /**
  97. * Constructs an empty list.
  98. */
  99. public LinkedList() {
  100. }
  101. /**
  102. * Constructs a list containing the elements of the specified
  103. * collection, in the order they are returned by the collection's
  104. * iterator.
  105. *
  106. * @param c the collection whose elements are to be placed into this list
  107. * @throws NullPointerException if the specified collection is null
  108. */
  109. public LinkedList(Collection<? extends E> c) {
  110. this();
  111. addAll(c);
  112. }
  113. /**
  114. * Links e as first element.
  115. */
  116. private void linkFirst(E e) {
  117. final Node<E> f = first;
  118. final Node<E> newNode = new Node<>(null, e, f);
  119. first = newNode;
  120. if (f == null)
  121. last = newNode;
  122. else
  123. f.prev = newNode;
  124. size++;
  125. modCount++;
  126. }
  127. /**
  128. * Links e as last element.
  129. */
  130. void linkLast(E e) {
  131. final Node<E> l = last;
  132. final Node<E> newNode = new Node<>(l, e, null);
  133. last = newNode;
  134. if (l == null)
  135. first = newNode;
  136. else
  137. l.next = newNode;
  138. size++;
  139. modCount++;
  140. }
  141. /**
  142. * Inserts element e before non-null Node succ.
  143. */
  144. void linkBefore(E e, Node<E> succ) {
  145. // assert succ != null;
  146. final Node<E> pred = succ.prev;
  147. final Node<E> newNode = new Node<>(pred, e, succ);
  148. succ.prev = newNode;
  149. if (pred == null)
  150. first = newNode;
  151. else
  152. pred.next = newNode;
  153. size++;
  154. modCount++;
  155. }
  156. /**
  157. * Unlinks non-null first node f.
  158. */
  159. private E unlinkFirst(Node<E> f) {
  160. // assert f == first && f != null;
  161. final E element = f.item;
  162. final Node<E> next = f.next;
  163. f.item = null;
  164. f.next = null; // help GC
  165. first = next;
  166. if (next == null)
  167. last = null;
  168. else
  169. next.prev = null;
  170. size--;
  171. modCount++;
  172. return element;
  173. }
  174. /**
  175. * Unlinks non-null last node l.
  176. */
  177. private E unlinkLast(Node<E> l) {
  178. // assert l == last && l != null;
  179. final E element = l.item;
  180. final Node<E> prev = l.prev;
  181. l.item = null;
  182. l.prev = null; // help GC
  183. last = prev;
  184. if (prev == null)
  185. first = null;
  186. else
  187. prev.next = null;
  188. size--;
  189. modCount++;
  190. return element;
  191. }
  192. /**
  193. * Unlinks non-null node x.
  194. */
  195. E unlink(Node<E> x) {
  196. // assert x != null;
  197. final E element = x.item;
  198. final Node<E> next = x.next;
  199. final Node<E> prev = x.prev;
  200. if (prev == null) {
  201. first = next;
  202. } else {
  203. prev.next = next;
  204. x.prev = null;
  205. }
  206. if (next == null) {
  207. last = prev;
  208. } else {
  209. next.prev = prev;
  210. x.next = null;
  211. }
  212. x.item = null;
  213. size--;
  214. modCount++;
  215. return element;
  216. }
  217. /**
  218. * Returns the first element in this list.
  219. *
  220. * @return the first element in this list
  221. * @throws NoSuchElementException if this list is empty
  222. */
  223. public E getFirst() {
  224. final Node<E> f = first;
  225. if (f == null)
  226. throw new NoSuchElementException();
  227. return f.item;
  228. }
  229. /**
  230. * Returns the last element in this list.
  231. *
  232. * @return the last element in this list
  233. * @throws NoSuchElementException if this list is empty
  234. */
  235. public E getLast() {
  236. final Node<E> l = last;
  237. if (l == null)
  238. throw new NoSuchElementException();
  239. return l.item;
  240. }
  241. /**
  242. * Removes and returns the first element from this list.
  243. *
  244. * @return the first element from this list
  245. * @throws NoSuchElementException if this list is empty
  246. */
  247. public E removeFirst() {
  248. final Node<E> f = first;
  249. if (f == null)
  250. throw new NoSuchElementException();
  251. return unlinkFirst(f);
  252. }
  253. /**
  254. * Removes and returns the last element from this list.
  255. *
  256. * @return the last element from this list
  257. * @throws NoSuchElementException if this list is empty
  258. */
  259. public E removeLast() {
  260. final Node<E> l = last;
  261. if (l == null)
  262. throw new NoSuchElementException();
  263. return unlinkLast(l);
  264. }
  265. /**
  266. * Inserts the specified element at the beginning of this list.
  267. *
  268. * @param e the element to add
  269. */
  270. public void addFirst(E e) {
  271. linkFirst(e);
  272. }
  273. /**
  274. * Appends the specified element to the end of this list.
  275. *
  276. * <p>This method is equivalent to {@link #add}.
  277. *
  278. * @param e the element to add
  279. */
  280. public void addLast(E e) {
  281. linkLast(e);
  282. }
  283. /**
  284. * Returns {@code true} if this list contains the specified element.
  285. * More formally, returns {@code true} if and only if this list contains
  286. * at least one element {@code e} such that
  287. * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
  288. *
  289. * @param o element whose presence in this list is to be tested
  290. * @return {@code true} if this list contains the specified element
  291. */
  292. public boolean contains(Object o) {
  293. return indexOf(o) != -1;
  294. }
  295. /**
  296. * Returns the number of elements in this list.
  297. *
  298. * @return the number of elements in this list
  299. */
  300. public int size() {
  301. return size;
  302. }
  303. /**
  304. * Appends the specified element to the end of this list.
  305. *
  306. * <p>This method is equivalent to {@link #addLast}.
  307. *
  308. * @param e element to be appended to this list
  309. * @return {@code true} (as specified by {@link Collection#add})
  310. */
  311. public boolean add(E e) {
  312. linkLast(e);
  313. return true;
  314. }
  315. /**
  316. * Removes the first occurrence of the specified element from this list,
  317. * if it is present. If this list does not contain the element, it is
  318. * unchanged. More formally, removes the element with the lowest index
  319. * {@code i} such that
  320. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
  321. * (if such an element exists). Returns {@code true} if this list
  322. * contained the specified element (or equivalently, if this list
  323. * changed as a result of the call).
  324. *
  325. * @param o element to be removed from this list, if present
  326. * @return {@code true} if this list contained the specified element
  327. */
  328. public boolean remove(Object o) {
  329. if (o == null) {
  330. for (Node<E> x = first; x != null; x = x.next) {
  331. if (x.item == null) {
  332. unlink(x);
  333. return true;
  334. }
  335. }
  336. } else {
  337. for (Node<E> x = first; x != null; x = x.next) {
  338. if (o.equals(x.item)) {
  339. unlink(x);
  340. return true;
  341. }
  342. }
  343. }
  344. return false;
  345. }
  346. /**
  347. * Appends all of the elements in the specified collection to the end of
  348. * this list, in the order that they are returned by the specified
  349. * collection's iterator. The behavior of this operation is undefined if
  350. * the specified collection is modified while the operation is in
  351. * progress. (Note that this will occur if the specified collection is
  352. * this list, and it's nonempty.)
  353. *
  354. * @param c collection containing elements to be added to this list
  355. * @return {@code true} if this list changed as a result of the call
  356. * @throws NullPointerException if the specified collection is null
  357. */
  358. public boolean addAll(Collection<? extends E> c) {
  359. return addAll(size, c);
  360. }
  361. /**
  362. * Inserts all of the elements in the specified collection into this
  363. * list, starting at the specified position. Shifts the element
  364. * currently at that position (if any) and any subsequent elements to
  365. * the right (increases their indices). The new elements will appear
  366. * in the list in the order that they are returned by the
  367. * specified collection's iterator.
  368. *
  369. * @param index index at which to insert the first element
  370. * from the specified collection
  371. * @param c collection containing elements to be added to this list
  372. * @return {@code true} if this list changed as a result of the call
  373. * @throws IndexOutOfBoundsException {@inheritDoc}
  374. * @throws NullPointerException if the specified collection is null
  375. */
  376. public boolean addAll(int index, Collection<? extends E> c) {
  377. checkPositionIndex(index);
  378. Object[] a = c.toArray();
  379. int numNew = a.length;
  380. if (numNew == 0)
  381. return false;
  382. Node<E> pred, succ;
  383. if (index == size) {
  384. succ = null;
  385. pred = last;
  386. } else {
  387. succ = node(index);
  388. pred = succ.prev;
  389. }
  390. for (Object o : a) {
  391. @SuppressWarnings("unchecked") E e = (E) o;
  392. Node<E> newNode = new Node<>(pred, e, null);
  393. if (pred == null)
  394. first = newNode;
  395. else
  396. pred.next = newNode;
  397. pred = newNode;
  398. }
  399. if (succ == null) {
  400. last = pred;
  401. } else {
  402. pred.next = succ;
  403. succ.prev = pred;
  404. }
  405. size += numNew;
  406. modCount++;
  407. return true;
  408. }
  409. /**
  410. * Removes all of the elements from this list.
  411. * The list will be empty after this call returns.
  412. */
  413. public void clear() {
  414. // Clearing all of the links between nodes is "unnecessary", but:
  415. // - helps a generational GC if the discarded nodes inhabit
  416. // more than one generation
  417. // - is sure to free memory even if there is a reachable Iterator
  418. for (Node<E> x = first; x != null; ) {
  419. Node<E> next = x.next;
  420. x.item = null;
  421. x.next = null;
  422. x.prev = null;
  423. x = next;
  424. }
  425. first = last = null;
  426. size = 0;
  427. modCount++;
  428. }
  429. // Positional Access Operations
  430. /**
  431. * Returns the element at the specified position in this list.
  432. *
  433. * @param index index of the element to return
  434. * @return the element at the specified position in this list
  435. * @throws IndexOutOfBoundsException {@inheritDoc}
  436. */
  437. public E get(int index) {
  438. checkElementIndex(index);
  439. return node(index).item;
  440. }
  441. /**
  442. * Replaces the element at the specified position in this list with the
  443. * specified element.
  444. *
  445. * @param index index of the element to replace
  446. * @param element element to be stored at the specified position
  447. * @return the element previously at the specified position
  448. * @throws IndexOutOfBoundsException {@inheritDoc}
  449. */
  450. public E set(int index, E element) {
  451. checkElementIndex(index);
  452. Node<E> x = node(index);
  453. E oldVal = x.item;
  454. x.item = element;
  455. return oldVal;
  456. }
  457. /**
  458. * Inserts the specified element at the specified position in this list.
  459. * Shifts the element currently at that position (if any) and any
  460. * subsequent elements to the right (adds one to their indices).
  461. *
  462. * @param index index at which the specified element is to be inserted
  463. * @param element element to be inserted
  464. * @throws IndexOutOfBoundsException {@inheritDoc}
  465. */
  466. public void add(int index, E element) {
  467. checkPositionIndex(index);
  468. if (index == size)
  469. linkLast(element);
  470. else
  471. linkBefore(element, node(index));
  472. }
  473. /**
  474. * Removes the element at the specified position in this list. Shifts any
  475. * subsequent elements to the left (subtracts one from their indices).
  476. * Returns the element that was removed from the list.
  477. *
  478. * @param index the index of the element to be removed
  479. * @return the element previously at the specified position
  480. * @throws IndexOutOfBoundsException {@inheritDoc}
  481. */
  482. public E remove(int index) {
  483. checkElementIndex(index);
  484. return unlink(node(index));
  485. }
  486. /**
  487. * Tells if the argument is the index of an existing element.
  488. */
  489. private boolean isElementIndex(int index) {
  490. return index >= 0 && index < size;
  491. }
  492. /**
  493. * Tells if the argument is the index of a valid position for an
  494. * iterator or an add operation.
  495. */
  496. private boolean isPositionIndex(int index) {
  497. return index >= 0 && index <= size;
  498. }
  499. /**
  500. * Constructs an IndexOutOfBoundsException detail message.
  501. * Of the many possible refactorings of the error handling code,
  502. * this "outlining" performs best with both server and client VMs.
  503. */
  504. private String outOfBoundsMsg(int index) {
  505. return "Index: "+index+", Size: "+size;
  506. }
  507. private void checkElementIndex(int index) {
  508. if (!isElementIndex(index))
  509. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  510. }
  511. private void checkPositionIndex(int index) {
  512. if (!isPositionIndex(index))
  513. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  514. }
  515. /**
  516. * Returns the (non-null) Node at the specified element index.
  517. */
  518. Node<E> node(int index) {
  519. // assert isElementIndex(index);
  520. if (index < (size >> 1)) {
  521. Node<E> x = first;
  522. for (int i = 0; i < index; i++)
  523. x = x.next;
  524. return x;
  525. } else {
  526. Node<E> x = last;
  527. for (int i = size - 1; i > index; i--)
  528. x = x.prev;
  529. return x;
  530. }
  531. }
  532. // Search Operations
  533. /**
  534. * Returns the index of the first occurrence of the specified element
  535. * in this list, or -1 if this list does not contain the element.
  536. * More formally, returns the lowest index {@code i} such that
  537. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  538. * or -1 if there is no such index.
  539. *
  540. * @param o element to search for
  541. * @return the index of the first occurrence of the specified element in
  542. * this list, or -1 if this list does not contain the element
  543. */
  544. public int indexOf(Object o) {
  545. int index = 0;
  546. if (o == null) {
  547. for (Node<E> x = first; x != null; x = x.next) {
  548. if (x.item == null)
  549. return index;
  550. index++;
  551. }
  552. } else {
  553. for (Node<E> x = first; x != null; x = x.next) {
  554. if (o.equals(x.item))
  555. return index;
  556. index++;
  557. }
  558. }
  559. return -1;
  560. }
  561. /**
  562. * Returns the index of the last occurrence of the specified element
  563. * in this list, or -1 if this list does not contain the element.
  564. * More formally, returns the highest index {@code i} such that
  565. * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
  566. * or -1 if there is no such index.
  567. *
  568. * @param o element to search for
  569. * @return the index of the last occurrence of the specified element in
  570. * this list, or -1 if this list does not contain the element
  571. */
  572. public int lastIndexOf(Object o) {
  573. int index = size;
  574. if (o == null) {
  575. for (Node<E> x = last; x != null; x = x.prev) {
  576. index--;
  577. if (x.item == null)
  578. return index;
  579. }
  580. } else {
  581. for (Node<E> x = last; x != null; x = x.prev) {
  582. index--;
  583. if (o.equals(x.item))
  584. return index;
  585. }
  586. }
  587. return -1;
  588. }
  589. // Queue operations.
  590. /**
  591. * Retrieves, but does not remove, the head (first element) of this list.
  592. *
  593. * @return the head of this list, or {@code null} if this list is empty
  594. * @since 1.5
  595. */
  596. public E peek() {
  597. final Node<E> f = first;
  598. return (f == null) ? null : f.item;
  599. }
  600. /**
  601. * Retrieves, but does not remove, the head (first element) of this list.
  602. *
  603. * @return the head of this list
  604. * @throws NoSuchElementException if this list is empty
  605. * @since 1.5
  606. */
  607. public E element() {
  608. return getFirst();
  609. }
  610. /**
  611. * Retrieves and removes the head (first element) of this list.
  612. *
  613. * @return the head of this list, or {@code null} if this list is empty
  614. * @since 1.5
  615. */
  616. public E poll() {
  617. final Node<E> f = first;
  618. return (f == null) ? null : unlinkFirst(f);
  619. }
  620. /**
  621. * Retrieves and removes the head (first element) of this list.
  622. *
  623. * @return the head of this list
  624. * @throws NoSuchElementException if this list is empty
  625. * @since 1.5
  626. */
  627. public E remove() {
  628. return removeFirst();
  629. }
  630. /**
  631. * Adds the specified element as the tail (last element) of this list.
  632. *
  633. * @param e the element to add
  634. * @return {@code true} (as specified by {@link Queue#offer})
  635. * @since 1.5
  636. */
  637. public boolean offer(E e) {
  638. return add(e);
  639. }
  640. // Deque operations
  641. /**
  642. * Inserts the specified element at the front of this list.
  643. *
  644. * @param e the element to insert
  645. * @return {@code true} (as specified by {@link Deque#offerFirst})
  646. * @since 1.6
  647. */
  648. public boolean offerFirst(E e) {
  649. addFirst(e);
  650. return true;
  651. }
  652. /**
  653. * Inserts the specified element at the end of this list.
  654. *
  655. * @param e the element to insert
  656. * @return {@code true} (as specified by {@link Deque#offerLast})
  657. * @since 1.6
  658. */
  659. public boolean offerLast(E e) {
  660. addLast(e);
  661. return true;
  662. }
  663. /**
  664. * Retrieves, but does not remove, the first element of this list,
  665. * or returns {@code null} if this list is empty.
  666. *
  667. * @return the first element of this list, or {@code null}
  668. * if this list is empty
  669. * @since 1.6
  670. */
  671. public E peekFirst() {
  672. final Node<E> f = first;
  673. return (f == null) ? null : f.item;
  674. }
  675. /**
  676. * Retrieves, but does not remove, the last element of this list,
  677. * or returns {@code null} if this list is empty.
  678. *
  679. * @return the last element of this list, or {@code null}
  680. * if this list is empty
  681. * @since 1.6
  682. */
  683. public E peekLast() {
  684. final Node<E> l = last;
  685. return (l == null) ? null : l.item;
  686. }
  687. /**
  688. * Retrieves and removes the first element of this list,
  689. * or returns {@code null} if this list is empty.
  690. *
  691. * @return the first element of this list, or {@code null} if
  692. * this list is empty
  693. * @since 1.6
  694. */
  695. public E pollFirst() {
  696. final Node<E> f = first;
  697. return (f == null) ? null : unlinkFirst(f);
  698. }
  699. /**
  700. * Retrieves and removes the last element of this list,
  701. * or returns {@code null} if this list is empty.
  702. *
  703. * @return the last element of this list, or {@code null} if
  704. * this list is empty
  705. * @since 1.6
  706. */
  707. public E pollLast() {
  708. final Node<E> l = last;
  709. return (l == null) ? null : unlinkLast(l);
  710. }
  711. /**
  712. * Pushes an element onto the stack represented by this list. In other
  713. * words, inserts the element at the front of this list.
  714. *
  715. * <p>This method is equivalent to {@link #addFirst}.
  716. *
  717. * @param e the element to push
  718. * @since 1.6
  719. */
  720. public void push(E e) {
  721. addFirst(e);
  722. }
  723. /**
  724. * Pops an element from the stack represented by this list. In other
  725. * words, removes and returns the first element of this list.
  726. *
  727. * <p>This method is equivalent to {@link #removeFirst()}.
  728. *
  729. * @return the element at the front of this list (which is the top
  730. * of the stack represented by this list)
  731. * @throws NoSuchElementException if this list is empty
  732. * @since 1.6
  733. */
  734. public E pop() {
  735. return removeFirst();
  736. }
  737. /**
  738. * Removes the first occurrence of the specified element in this
  739. * list (when traversing the list from head to tail). If the list
  740. * does not contain the element, it is unchanged.
  741. *
  742. * @param o element to be removed from this list, if present
  743. * @return {@code true} if the list contained the specified element
  744. * @since 1.6
  745. */
  746. public boolean removeFirstOccurrence(Object o) {
  747. return remove(o);
  748. }
  749. /**
  750. * Removes the last occurrence of the specified element in this
  751. * list (when traversing the list from head to tail). If the list
  752. * does not contain the element, it is unchanged.
  753. *
  754. * @param o element to be removed from this list, if present
  755. * @return {@code true} if the list contained the specified element
  756. * @since 1.6
  757. */
  758. public boolean removeLastOccurrence(Object o) {
  759. if (o == null) {
  760. for (Node<E> x = last; x != null; x = x.prev) {
  761. if (x.item == null) {
  762. unlink(x);
  763. return true;
  764. }
  765. }
  766. } else {
  767. for (Node<E> x = last; x != null; x = x.prev) {
  768. if (o.equals(x.item)) {
  769. unlink(x);
  770. return true;
  771. }
  772. }
  773. }
  774. return false;
  775. }
  776. /**
  777. * Returns a list-iterator of the elements in this list (in proper
  778. * sequence), starting at the specified position in the list.
  779. * Obeys the general contract of {@code List.listIterator(int)}.<p>
  780. *
  781. * The list-iterator is <i>fail-fast</i>: if the list is structurally
  782. * modified at any time after the Iterator is created, in any way except
  783. * through the list-iterator's own {@code remove} or {@code add}
  784. * methods, the list-iterator will throw a
  785. * {@code ConcurrentModificationException}. Thus, in the face of
  786. * concurrent modification, the iterator fails quickly and cleanly, rather
  787. * than risking arbitrary, non-deterministic behavior at an undetermined
  788. * time in the future.
  789. *
  790. * @param index index of the first element to be returned from the
  791. * list-iterator (by a call to {@code next})
  792. * @return a ListIterator of the elements in this list (in proper
  793. * sequence), starting at the specified position in the list
  794. * @throws IndexOutOfBoundsException {@inheritDoc}
  795. * @see List#listIterator(int)
  796. */
  797. public ListIterator<E> listIterator(int index) {
  798. checkPositionIndex(index);
  799. return new ListItr(index);
  800. }
  801. private class ListItr implements ListIterator<E> {
  802. private Node<E> lastReturned;
  803. private Node<E> next;
  804. private int nextIndex;
  805. private int expectedModCount = modCount;
  806. ListItr(int index) {
  807. // assert isPositionIndex(index);
  808. next = (index == size) ? null : node(index);
  809. nextIndex = index;
  810. }
  811. public boolean hasNext() {
  812. return nextIndex < size;
  813. }
  814. public E next() {
  815. checkForComodification();
  816. if (!hasNext())
  817. throw new NoSuchElementException();
  818. lastReturned = next;
  819. next = next.next;
  820. nextIndex++;
  821. return lastReturned.item;
  822. }
  823. public boolean hasPrevious() {
  824. return nextIndex > 0;
  825. }
  826. public E previous() {
  827. checkForComodification();
  828. if (!hasPrevious())
  829. throw new NoSuchElementException();
  830. lastReturned = next = (next == null) ? last : next.prev;
  831. nextIndex--;
  832. return lastReturned.item;
  833. }
  834. public int nextIndex() {
  835. return nextIndex;
  836. }
  837. public int previousIndex() {
  838. return nextIndex - 1;
  839. }
  840. public void remove() {
  841. checkForComodification();
  842. if (lastReturned == null)
  843. throw new IllegalStateException();
  844. Node<E> lastNext = lastReturned.next;
  845. unlink(lastReturned);
  846. if (next == lastReturned)
  847. next = lastNext;
  848. else
  849. nextIndex--;
  850. lastReturned = null;
  851. expectedModCount++;
  852. }
  853. public void set(E e) {
  854. if (lastReturned == null)
  855. throw new IllegalStateException();
  856. checkForComodification();
  857. lastReturned.item = e;
  858. }
  859. public void add(E e) {
  860. checkForComodification();
  861. lastReturned = null;
  862. if (next == null)
  863. linkLast(e);
  864. else
  865. linkBefore(e, next);
  866. nextIndex++;
  867. expectedModCount++;
  868. }
  869. public void forEachRemaining(Consumer<? super E> action) {
  870. Objects.requireNonNull(action);
  871. while (modCount == expectedModCount && nextIndex < size) {
  872. action.accept(next.item);
  873. lastReturned = next;
  874. next = next.next;
  875. nextIndex++;
  876. }
  877. checkForComodification();
  878. }
  879. final void checkForComodification() {
  880. if (modCount != expectedModCount)
  881. throw new ConcurrentModificationException();
  882. }
  883. }
  884. private static class Node<E> {
  885. E item;
  886. Node<E> next;
  887. Node<E> prev;
  888. Node(Node<E> prev, E element, Node<E> next) {
  889. this.item = element;
  890. this.next = next;
  891. this.prev = prev;
  892. }
  893. }
  894. /**
  895. * @since 1.6
  896. */
  897. public Iterator<E> descendingIterator() {
  898. return new DescendingIterator();
  899. }
  900. /**
  901. * Adapter to provide descending iterators via ListItr.previous
  902. */
  903. private class DescendingIterator implements Iterator<E> {
  904. private final ListItr itr = new ListItr(size());
  905. public boolean hasNext() {
  906. return itr.hasPrevious();
  907. }
  908. public E next() {
  909. return itr.previous();
  910. }
  911. public void remove() {
  912. itr.remove();
  913. }
  914. }
  915. @SuppressWarnings("unchecked")
  916. private LinkedList<E> superClone() {
  917. try {
  918. return (LinkedList<E>) super.clone();
  919. } catch (CloneNotSupportedException e) {
  920. throw new InternalError(e);
  921. }
  922. }
  923. /**
  924. * Returns a shallow copy of this {@code LinkedList}. (The elements
  925. * themselves are not cloned.)
  926. *
  927. * @return a shallow copy of this {@code LinkedList} instance
  928. */
  929. public Object clone() {
  930. LinkedList<E> clone = superClone();
  931. // Put clone into "virgin" state
  932. clone.first = clone.last = null;
  933. clone.size = 0;
  934. clone.modCount = 0;
  935. // Initialize clone with our elements
  936. for (Node<E> x = first; x != null; x = x.next)
  937. clone.add(x.item);
  938. return clone;
  939. }
  940. /**
  941. * Returns an array containing all of the elements in this list
  942. * in proper sequence (from first to last element).
  943. *
  944. * <p>The returned array will be "safe" in that no references to it are
  945. * maintained by this list. (In other words, this method must allocate
  946. * a new array). The caller is thus free to modify the returned array.
  947. *
  948. * <p>This method acts as bridge between array-based and collection-based
  949. * APIs.
  950. *
  951. * @return an array containing all of the elements in this list
  952. * in proper sequence
  953. */
  954. public Object[] toArray() {
  955. Object[] result = new Object[size];
  956. int i = 0;
  957. for (Node<E> x = first; x != null; x = x.next)
  958. result[i++] = x.item;
  959. return result;
  960. }
  961. /**
  962. * Returns an array containing all of the elements in this list in
  963. * proper sequence (from first to last element); the runtime type of
  964. * the returned array is that of the specified array. If the list fits
  965. * in the specified array, it is returned therein. Otherwise, a new
  966. * array is allocated with the runtime type of the specified array and
  967. * the size of this list.
  968. *
  969. * <p>If the list fits in the specified array with room to spare (i.e.,
  970. * the array has more elements than the list), the element in the array
  971. * immediately following the end of the list is set to {@code null}.
  972. * (This is useful in determining the length of the list <i>only</i> if
  973. * the caller knows that the list does not contain any null elements.)
  974. *
  975. * <p>Like the {@link #toArray()} method, this method acts as bridge between
  976. * array-based and collection-based APIs. Further, this method allows
  977. * precise control over the runtime type of the output array, and may,
  978. * under certain circumstances, be used to save allocation costs.
  979. *
  980. * <p>Suppose {@code x} is a list known to contain only strings.
  981. * The following code can be used to dump the list into a newly
  982. * allocated array of {@code String}:
  983. *
  984. * <pre>
  985. * String[] y = x.toArray(new String[0]);</pre>
  986. *
  987. * Note that {@code toArray(new Object[0])} is identical in function to
  988. * {@code toArray()}.
  989. *
  990. * @param a the array into which the elements of the list are to
  991. * be stored, if it is big enough; otherwise, a new array of the
  992. * same runtime type is allocated for this purpose.
  993. * @return an array containing the elements of the list
  994. * @throws ArrayStoreException if the runtime type of the specified array
  995. * is not a supertype of the runtime type of every element in
  996. * this list
  997. * @throws NullPointerException if the specified array is null
  998. */
  999. @SuppressWarnings("unchecked")
  1000. public <T> T[] toArray(T[] a) {
  1001. if (a.length < size)
  1002. a = (T[])java.lang.reflect.Array.newInstance(
  1003. a.getClass().getComponentType(), size);
  1004. int i = 0;
  1005. Object[] result = a;
  1006. for (Node<E> x = first; x != null; x = x.next)
  1007. result[i++] = x.item;
  1008. if (a.length > size)
  1009. a[size] = null;
  1010. return a;
  1011. }
  1012. private static final long serialVersionUID = 876323262645176354L;
  1013. /**
  1014. * Saves the state of this {@code LinkedList} instance to a stream
  1015. * (that is, serializes it).
  1016. *
  1017. * @serialData The size of the list (the number of elements it
  1018. * contains) is emitted (int), followed by all of its
  1019. * elements (each an Object) in the proper order.
  1020. */
  1021. private void writeObject(java.io.ObjectOutputStream s)
  1022. throws java.io.IOException {
  1023. // Write out any hidden serialization magic
  1024. s.defaultWriteObject();
  1025. // Write out size
  1026. s.writeInt(size);
  1027. // Write out all elements in the proper order.
  1028. for (Node<E> x = first; x != null; x = x.next)
  1029. s.writeObject(x.item);
  1030. }
  1031. /**
  1032. * Reconstitutes this {@code LinkedList} instance from a stream
  1033. * (that is, deserializes it).
  1034. */
  1035. @SuppressWarnings("unchecked")
  1036. private void readObject(java.io.ObjectInputStream s)
  1037. throws java.io.IOException, ClassNotFoundException {
  1038. // Read in any hidden serialization magic
  1039. s.defaultReadObject();
  1040. // Read in size
  1041. int size = s.readInt();
  1042. // Read in all elements in the proper order.
  1043. for (int i = 0; i < size; i++)
  1044. linkLast((E)s.readObject());
  1045. }
  1046. /**
  1047. * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
  1048. * and <em>fail-fast</em> {@link Spliterator} over the elements in this
  1049. * list.
  1050. *
  1051. * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and
  1052. * {@link Spliterator#ORDERED}. Overriding implementations should document
  1053. * the reporting of additional characteristic values.
  1054. *
  1055. * @implNote
  1056. * The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}
  1057. * and implements {@code trySplit} to permit limited parallelism..
  1058. *
  1059. * @return a {@code Spliterator} over the elements in this list
  1060. * @since 1.8
  1061. */
  1062. @Override
  1063. public Spliterator<E> spliterator() {
  1064. return new LLSpliterator<E>(this, -1, 0);
  1065. }
  1066. /** A customized variant of Spliterators.IteratorSpliterator */
  1067. static final class LLSpliterator<E> implements Spliterator<E> {
  1068. static final int BATCH_UNIT = 1 << 10; // batch array size increment
  1069. static final int MAX_BATCH = 1 << 25; // max batch array size;
  1070. final LinkedList<E> list; // null OK unless traversed
  1071. Node<E> current; // current node; null until initialized
  1072. int est; // size estimate; -1 until first needed
  1073. int expectedModCount; // initialized when est set
  1074. int batch; // batch size for splits
  1075. LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {
  1076. this.list = list;
  1077. this.est = est;
  1078. this.expectedModCount = expectedModCount;
  1079. }
  1080. final int getEst() {
  1081. int s; // force initialization
  1082. final LinkedList<E> lst;
  1083. if ((s = est) < 0) {
  1084. if ((lst = list) == null)
  1085. s = est = 0;
  1086. else {
  1087. expectedModCount = lst.modCount;
  1088. current = lst.first;
  1089. s = est = lst.size;
  1090. }
  1091. }
  1092. return s;
  1093. }
  1094. public long estimateSize() { return (long) getEst(); }
  1095. public Spliterator<E> trySplit() {
  1096. Node<E> p;
  1097. int s = getEst();
  1098. if (s > 1 && (p = current) != null) {
  1099. int n = batch + BATCH_UNIT;
  1100. if (n > s)
  1101. n = s;
  1102. if (n > MAX_BATCH)
  1103. n = MAX_BATCH;
  1104. Object[] a = new Object[n];
  1105. int j = 0;
  1106. do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
  1107. current = p;
  1108. batch = j;
  1109. est = s - j;
  1110. return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
  1111. }
  1112. return null;
  1113. }
  1114. public void forEachRemaining(Consumer<? super E> action) {
  1115. Node<E> p; int n;
  1116. if (action == null) throw new NullPointerException();
  1117. if ((n = getEst()) > 0 && (p = current) != null) {
  1118. current = null;
  1119. est = 0;
  1120. do {
  1121. E e = p.item;
  1122. p = p.next;
  1123. action.accept(e);
  1124. } while (p != null && --n > 0);
  1125. }
  1126. if (list.modCount != expectedModCount)
  1127. throw new ConcurrentModificationException();
  1128. }
  1129. public boolean tryAdvance(Consumer<? super E> action) {
  1130. Node<E> p;
  1131. if (action == null) throw new NullPointerException();
  1132. if (getEst() > 0 && (p = current) != null) {
  1133. --est;
  1134. E e = p.item;
  1135. current = p.next;
  1136. action.accept(e);
  1137. if (list.modCount != expectedModCount)
  1138. throw new ConcurrentModificationException();
  1139. return true;
  1140. }
  1141. return false;
  1142. }
  1143. public int characteristics() {
  1144. return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
  1145. }
  1146. }
  1147. }

参考

原文链接:https://www.cnblogs.com/liuyun1995/p/8287707.html

Java集合基于JDK1.8的LinkedList源码分析的更多相关文章

  1. Java集合基于JDK1.8的ArrayList源码分析

    本篇分析ArrayList的源码,在分析之前先跟大家谈一谈数组.数组可能是我们最早接触到的数据结构之一,它是在内存中划分出一块连续的地址空间用来进行元素的存储,由于它直接操作内存,所以数组的性能要比集 ...

  2. Java -- 基于JDK1.8的LinkedList源码分析

    1,上周末我们一起分析了ArrayList的源码并进行了一些总结,因为最近在看Collection这一块的东西,下面的图也是大致的总结了Collection里面重要的接口和类,如果没有意外的话后面基本 ...

  3. 基于JDK1.8的LinkedList源码学习笔记

    LinkedList作为一种常用的List,是除了ArrayList之外最有用的List.其同样实现了List接口,但是除此之外它同样实现了Deque接口,而Deque是一个双端队列接口,其继承自Qu ...

  4. Java集合框架之二:LinkedList源码解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! LinkedList底层是通过双向循环链表来实现的,其结构如下图所示: 链表的组成元素我们称之为节点,节点由三部分组成:前一个节点的引用地 ...

  5. Java -- 基于JDK1.8的ArrayList源码分析

    1,前言 很久没有写博客了,很想念大家,18年都快过完了,才开始写第一篇,争取后面每周写点,权当是记录,因为最近在看JDK的Collection,而且ArrayList源码这一块也经常被面试官问道,所 ...

  6. Java 集合系列(四)—— ListIterator 源码分析

    以脑图的形式来展示Java集合知识,让零碎知识点形成体系 Iterator 对比   Iterator(迭代器)是一种设计模式,是一个对象,用于遍历集合中的所有元素.  Iterator 包含四个方法 ...

  7. 7.Java集合-Arrays类实现原理及源码分析

    Java集合---Arrays类源码解析  转自:http://www.cnblogs.com/ITtangtang/p/3948765.html 一.Arrays.sort()数组排序 Java A ...

  8. Java -- 基于JDK1.8的ThreadLocal源码分析

    1,最近在做一个需求的时候需要对外部暴露一个值得应用  ,一般来说直接写个单例,将这个成员变量的值暴露出去就ok了,但是当时突然灵机一动(现在回想是个多余的想法),想到handle源码里面有使用过Th ...

  9. java集合框架02——Collection架构与源码分析

    Collection是一个接口,它主要的两个分支是List和Set.如下图所示: List和Set都是接口,它们继承与Collection.List是有序的队列,可以用重复的元素:而Set是数学概念中 ...

随机推荐

  1. ERROR: but there is no YARN_RESOURCEMANAGER_USER defined. Aborting operation.

    将start-dfs.sh,stop-dfs.sh两个文件顶部添加以下参数 HDFS_NAMENODE_USER=root HDFS_DATANODE_USER=root HDFS_SECONDARY ...

  2. pta 7-1 找出不是两个数组共有的元素

    给定两个整型数组,本题要求找出不是两者共有的元素. 输入格式: 输入分别在两行中给出两个整型数组,每行先给出正整数N(≤20),随后是N个整数,其间以空格分隔. 输出格式: 在一行中按照数字给出的顺序 ...

  3. mysql 连接数据库时时区报错

    1.url: jdbc:mysql://192.168.0.101:3306/testdb?serverTimezone=UTC,在连接字符后面添加时区设置 2.使用navicat或者直接使用mysq ...

  4. mysql8 Could not retrieve transation read-only status server

    想回顾下ssm,看着网上别的帖子手动搭了一个,一直报Could not retrieve transation read-only status server , java.sql.SQLExcept ...

  5. 刷题56. Merge Intervals

    一.题目说明 题目是56. Merge Intervals,给定一列区间的集合,归并重叠区域. 二.我的做法 这个题目不难,先对intervals排序,然后取下一个集合,如果cur[0]>res ...

  6. 122、Java面向对象之直接输出对象本身

    01.代码如下: package TIANPAN; class Book { public void print() { // 调用print()方法的对象就是当前对象,this就自动与此对象指向同一 ...

  7. 《编写高质量iOS与OS X代码的52个有效方法》书籍目录

    一.熟悉Objective-C 1.了解Objective-C语言的起源 2.在类的头文件中尽量少引入其他头文件 3.多用字面量语法,少用与之等价的方法 4.多用类型常量,少用#define预处理指令 ...

  8. Oracle如何修改密码?如何解锁scott用户?

    修改密码: scott用户的密码不对,进入管理员用户,修改scott用户密码即可 或者这样修改密码:在运行栏里面敲:sqlplus(空格)/nolog 回车接着在弹出框里面敲:conn sys/pas ...

  9. 【mysql】mysq8.0新特性

    一.MySQL8.0简介   mysql8.0现在已经发布,2016-09-12第一个DM(development milestone)版本8.0.0发布.新的版本带来很多新功能和新特性,对性能也得到 ...

  10. Mybatis-问题总结

    1.在mybatis里面注释语句的时候,一定用 <!- -需要注释的内容–>.用快捷键注释一行代码显示是/**/,但是实际执行起来报错.