个人随笔
目录
JAVA集合框架-2-手写LinkedList框架
2019-02-18 22:45:46

本次手写是对照着LinkedList的源码来写的,没有封装接口什么的,只是单纯的实现功能

原理:链表

代码如下:

  1. package cn.myforever.mylist;
  2. /**
  3. * 手写linkedlist
  4. * 原理:双向链表
  5. * @author forever
  6. *
  7. * @param <E>
  8. */
  9. public class MyLinkedList<E> {
  10. /**
  11. * 定义一个静态内部类做节点
  12. * @author forever
  13. *
  14. * @param <E>
  15. *
  16. */
  17. private static class Node<E>{
  18. E e;
  19. Node<E> next;
  20. Node<E> prev;
  21. Node(Node<E> prev,E e,Node<E> next){
  22. this.e = e;
  23. this.next = next;
  24. this.prev = prev;
  25. }
  26. }
  27. //定义第一个节点的引用,作用是用于查询,跟第一个节点一起指向第一个节点的堆地址
  28. private Node<E> first;
  29. //定义第最后一个节点的引用,作用是用于插入,跟第最后节点一起指向最后一个节点的堆地址
  30. private Node<E> last;
  31. private int size;//大小
  32. /**
  33. * 添加节点都是在最后一个节点添加
  34. * @param e
  35. * @return
  36. */
  37. public Boolean add(E e) {
  38. //获取最后一个节点
  39. final Node<E> l = last;
  40. //添加节点都是在最后一个节点添加的,所以该节点的上一个节点就是最后一个节点,下一个节点为null
  41. final Node<E> newNode = new Node<E>(l, e, null);
  42. //把新节点变为最后一个节点
  43. last = newNode;
  44. if(l==null) {
  45. //这里就表明还没有开始和结束节点,这个节点就是第一个节点
  46. first = newNode;
  47. }else {
  48. //这里就表明已经有节点了,那么这个就是最后一个节点
  49. l.next = newNode;
  50. }
  51. size++;
  52. return true;
  53. }
  54. public Boolean add(int index,E e) {
  55. checkIndex(index);
  56. //然后获取这个位置的及诶单
  57. Node<E> node = getNode(index);
  58. if(index == size) {
  59. //在最后一个插入即可
  60. add(e);
  61. }else {
  62. //插入在node之前
  63. final Node<E> prev = node.prev;
  64. final Node<E> newNode = new Node<E>(prev, e, node);
  65. node.prev=newNode;
  66. if(prev==null) {
  67. first = newNode;
  68. }else{
  69. prev.next = newNode;
  70. }
  71. }
  72. size++;
  73. return true;
  74. }
  75. /**
  76. * 获取集合的大小
  77. * @return
  78. */
  79. public int size() {
  80. return size;
  81. }
  82. private void checkIndex(int index) {
  83. if(index>=size||index<0) {
  84. throw new IndexOutOfBoundsException("下标越界:"+index);
  85. }
  86. }
  87. /**
  88. * 获取值,这个方法相对于ArrayList来就比较慢了哦
  89. * @param index
  90. * @return
  91. */
  92. public E get(int index) {
  93. //检查有没有越界
  94. checkIndex(index);
  95. Node<E> node = getNode(index);
  96. return node.e;
  97. }
  98. /**
  99. * 移除
  100. * @param index
  101. * @return
  102. */
  103. public E remove(int index) {
  104. //先判断越界
  105. checkIndex(index);
  106. //获取这一个节点
  107. //查询只能先从first开始查起
  108. final Node<E> node =getNode(index);
  109. final E e = node.e;
  110. final Node<E> next = node.next;
  111. final Node<E> prev =node.prev;
  112. //如果上一个节点为null,就表明是第一个节点
  113. if(prev==null) {
  114. //指定下一个节点为第一个节点即可
  115. first =next;
  116. }else{
  117. prev.next=next;
  118. node.prev =null;
  119. }
  120. if(next==null) {
  121. last = prev;
  122. }else {
  123. next.prev=prev;
  124. node.next=null;
  125. }
  126. node.e=null;
  127. size--;
  128. return e;
  129. }
  130. /**
  131. * 移除元素这个方法因为不知到下标,效率太低,只能从一开始找起
  132. * @param e
  133. */
  134. public void remove(E e) {
  135. //获取元素下标
  136. int index = -1;
  137. Node<E> x = first;
  138. if(x!=null) {
  139. if(e.equals(x.e)) {
  140. index = 0;
  141. }
  142. }
  143. for(int i=0;i<size-1;i++) {
  144. x =x.next;
  145. if(e.equals(x.e)) {
  146. index =i+1;
  147. break;
  148. }
  149. }
  150. //这里就获取了下标,直接移除即可
  151. if(index!=-1) {
  152. remove(index);
  153. }
  154. }
  155. /**
  156. * 根据下标去获取
  157. * @param index
  158. * @return
  159. */
  160. private Node<E> getNode(int index){
  161. //简单的话就只需要从最开始查找即可,但是这样的话如果要查找的内容在最后一个,可能会效率很低
  162. //所以这里按位置来判断查找的方向
  163. if(index<(size>>1)) {
  164. Node<E> x = first;
  165. //因为用的是next,所以这里就直接index
  166. for (int i = 0; i <index; i++) {
  167. x = x.next;
  168. }
  169. return x;
  170. }else {
  171. Node<E> x = last;
  172. for (int i = size - 1; i > index; i--){
  173. x = x.prev;
  174. }
  175. return x;
  176. }
  177. }
  178. //清除
  179. public void clear() {
  180. for (Node<E> x = first; x != null; ) {
  181. Node<E> next = x.next;
  182. x.e = null;
  183. x.next = null;
  184. x.prev = null;
  185. x = next;
  186. }
  187. first = last = null;
  188. size = 0;
  189. }
  190. @Override
  191. public String toString() {
  192. String str = "";
  193. Node<E> x = first;
  194. str=x.e+";";
  195. //因为是next,所以就用size-1
  196. for (int i = 0; i <size-1; i++) {
  197. x = x.next;
  198. str+=x.e+";";
  199. }
  200. System.out.println(str);
  201. return "";
  202. }
  203. }

也蛮简单的,不算太难,主要原因是,照搬源码。
这里提供git地址:https://github.com/suibibk/my-linklist.git

 242

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2