前文:LinkedList以链表的方式操作数据,在使用查找节点的方法的时候先对下标折半,但是未使用二分法, 有点不太理解为什么没有使用,本文只是简单分析了几个常用的方法,之前也有看过源码但是发现不记录下来就 会忘记,所以今天还是花时间记录了一下,排版有点low,下次注意! //add(E e)方法 public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; //先将链表的最后一个节点记录下来 final Node<E> newNode = new Node<>(l, e, null); //new一个节点,并且将前一个节点指向链表的前最后一个节点 last = newNode; //将新节点赋给last if (l == null) first = newNode; //链表为null,将新增的节点赋给first else l.next = newNode; //l节点的next指向新节点 size++; modCount++; } //节点元素 private static class Node<E> { E item; //保存内容 Node<E> next; //下一个节点地址 Node<E> prev; //前一个节点 Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } //LinkedList类似于链表结构,用节点Node<E>来保存并且记录数据,不用验证添加内容是否为空 //addAll(Collection<? extends E> c) public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); //验证下标是否合法 Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; if (index == size) { //指定在最后位加入元素 succ = null; pred = last; } else { succ = node(index); pred = succ.prev; } for (Object o : a) { //遍历object[]数组,将元素一一加进去 @SuppressWarnings("unchecked") E e = (E) o; Node<E> newNode = new Node<>(pred, e, null); if (pred == null) // first = newNode; else pred.next = newNode; pred = newNode; //为下一个节点保存前节点 } if (succ == null) { //排除链表为空的情况 last = pred; } else { //将加进去的object[]数组的最后面的一个元素与之前返回指定index下标的元素连接起来 pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true; } //验证下标 private void checkPositionIndex(int index) { if (!isPositionIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //验证下标 private boolean isPositionIndex(int index) { return index >= 0 && index <= size; } //LinkedList的toArray()方法 public Object[] toArray() { Object[] result = new Object[size]; //创建一个固定长度的Object[]数组 int i = 0; for (Node<E> x = first; x != null; x = x.next) //遍历节点将节点的值一一拿出来放到Object[]数组中 result[i++] = x.item; return result; } */ Node<E> node(int index) { //在链表中查找对应index的位置 // assert isElementIndex(index); if (index < (size >> 1)) { //小于size链表长度的一半 Node<E> x = first; for (int i = 0; i < index; i++) //从第一个节点往后遍历前一半查找 x = x.next; //返回对应元素 return x; } else { Node<E> x = last; //从最后一个节点往前遍历查找 for (int i = size - 1; i > index; i--) //返回对应元素 x = x.prev; return x; } } //移除 public E remove(int index)
public E remove(int index) { checkElementIndex(index); return unlink(node(index)); //node(index)查找返回对应index的节点 } E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; //当前节点的前一个节点 final Node<E> prev = x.prev; //当前节点的下一个节点 if (prev == null) { //链表第一个节点 first = next; //next=null } else { prev.next = next; //x.pre的下一个节点更新为x.next x.prev = null; //置空x.pre } if (next == null) { //移除最后一个节点 last = prev; } else { next.prev = prev; //x.next的前节点更新为x.pre x.next = null; //置空x.next } x.item = null; //置空x.item size--; modCount++; return element; } //检查index private void checkElementIndex(int index) { if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } private boolean isElementIndex(int index) { return index >= 0 && index < size; } //get(int index)方法 public E get(int index) { checkElementIndex(index); return node(index).item; //根据下标折半查找 } //set(int index, E element) public E set(int index, E element) { checkElementIndex(index); Node<E> x = node(index); //根据下标折半查找指定元素 E oldVal = x.item; x.item = element; //将旧值覆盖 return oldVal; }
LinkedList源码解析
最新推荐文章于 2023-03-11 10:11:09 发布