本来开开心心写着代码,然后一运行,一堆的错误信息,瞬间心情就不好了,生产代码我这边就不贴出来了,下面老师以demo为例,给大家分享一下这个难过的历程。...首先我们要清楚LinkedList类的继承关系,如果是用IDEA开发的童靴,可以直接Ctrl+H查看类的继承关系。...那问题就可以转化为:为什么list的modCount和listTemp的modCount不一致呢,是哪个地方修改了它?...; if (prev == null) { first = next; } else { prev.next = next; x.prev...= null; } if (next == null) { last = prev; } else { next.prev = prev
现象与问题 add() 方法在迭代器位置前面添加一个新元素 next() 与 previous() 返回越过的对象 set() 方法替换的是 next() 和 previous() 方法返回的上一个元素...首先我们来分析 LinkedList 的 listIterator() 和 listIterator(int index) 方法获取 ListIterator 迭代器过程。...next.prev 节点 55 * 将处理目标储到 lastReturned 变量中 56 * 然后将当前的 next.prev 节点保存起来,用于下一次迭代处理...next() 处理的是 next 节点,返回 next.item previous() 处理的是 next.prev 节点 返回 next.prev.item remove() 处理的是 lastReturned...在 github 上建了一个 repository ,Java Core Knowledge Tree,各位看官若是喜欢请给个star,以示鼓励,谢谢。
这也是在我的文章中给大家贴很多源码的原因,毕竟讲的再好不如给大家一看。...在 Deque 中,可以划分为几部分代码,一部分是他自己用的常用操作,还有一些是 stack 用的,以及 queue,和 Collection 。...return true; } 至于 2个 addAll 方法,原理都一样,只是 循环调用构建 prev 和 next。...prev = x.prev; if (prev == null) { first = next; } else { prev.next...GC回收: x 的前驱指向后驱,如果 前驱 prev 是null,那么证明 x 是头部节点,修改头节点 first 指向后驱 next x 的后驱指向 前驱,如果后驱 next 是null,那么证明
;反之,如果不为null,则将prev的next节点指向succ,同时succ的prev节点指向pred。...null(包括item和next) 如果next节点(原first节点的nex节点)为null,则将last置为null值;如果不为null,则将next节点的prev属性置为null 然后修正元素个数以及修改次数...= 0; modCount++; } clear方法,从first开始遍历链表,将元素的item、prev和nex属性置为null值,然后将first和last置为null。...ListIterator示例 import java.util.Iterator; import java.util.LinkedList; public class LinkedListIteratorExample...(ele); } } } 输出结果: LinkedList ==> [23, 3, 17, 9, 42] listIterator~~ 23 3 17 9 42
这是关于 java 集合类源码的第四篇文章。...往期文章: java集合源码分析(一):Collection 与 AbstractCollection java集合源码分析(二):List与AbstractList java集合源码分析(三):ArrayList...forEach 由于 LinkedList 没有重写 forEach()方法,使用 forEach()仍然还是沿用 Iterable 接口提供的增强 for 循环实现,实际上编译以后还是用的迭代器,也就是说...modCount赋给成员变量 expectedModCount,因此,在迭代器里调用非迭代器自带的结构性操作方法,都会在第二次的并发修改检测的时候抛出异常。...; } } return -1; } 7.clear LinkedList 的 clear()就是把所有节点的引用关系清除,用注释的话来说: Clearing all
关于List接口的类结构和AbstractList的讲解,可以看看上一篇文章jdk源码追踪-ArrayList。...迭代器是实际调用抽象方法listIterator,需要子类实现,是LinkedList的父类。...AbstractList中list迭代器的实现是通过get(int index)和记录当前index来实现,对于链表来说,每次的next(),都意味着从头遍历到当前节点,这么做效率肯定很慢。...LinkedList的实现是保存上传返回结点lastReturned和下一个结点next。...next()执行时,将next的引用赋给lastReturned,next.next赋给next返回lastReturned的数据。
list类里面成员变量就有: private: Node* _head; 3.1 构造 先来一个无参构造,实现的双向带头循环链表,先定义哨兵位节点,让它的next和prev都指向自己: list..._node; } 4.5 begin 和 end begin执行第一个节点,也就是head的next iterator begin() { return iterator(_head-...,让新节点的prev指向tail,再把head的prev改为新节点,新节点的next改为head。...,和它前一个节点prev 还有它的后一个节点next。...然后让prev的_next 指向next;next的_prev 指向 prev。 删除会导致迭代器失效的问题,为了避免,就返回删除节点的下一个位置。
所有集合均实现了这个接口,比如HashSet,HashMap; 而如果是ListIterator接口,那么在遍历集合中元素的时候,可以实现双向遍历,既可以通过next()访问下一个元素,又可以通过previous...在Iterator基础上添加了add(),previous()和hasPrevious()方法 26 ListIterator aIter=a.listIterator(...只是在其中加入了双向链表的结构。插入的时候依然按照HashMap的方式插入,只是在元素之间用双向链表表示前后的顺序,所以查找和插入都很快速。...class Node { E item; Node next; Node prev; Node(Node prev, E element, Node... next) { this.item = element; this.next = next; this.prev = prev; } }
从Java源码上分析为什么LinkedList随机访问比顺序访问要慢这么多?...List, Deque, Cloneable, java.io.Serializable { // 返回此列表中指定位置的元素。...public Iterator iterator() { return listIterator(); } // 返回参数为0的列表迭代器 public ListIterator...; // 将实际修改集合次数赋值给预期修改次数 private int expectedModCount = modCount; ListItr(int...null : node(index); // 将index的值赋值给 nextIndex,便于下次查找 nextIndex = index;
java编码中,集合类算是我们用的最多的,比如HashMap,TreeMap,ArrayList,LinkedList等等,使我们最常用的(并发包中的实现暂不做分析),按照顶级接口分析,有两种,...中间用到了一些扩容和数组复制的方法也都贴了出了,接下来对其逐步详细分解。...Node prev; Node(Node prev, E element, Node next) { this.item = element; this.next = next...linkFirst方法中f暂存首节点first,然后根据入参e新建一个prev指针null,next指针为f的节点,然后把新节点赋值给first,如果f为null(之前没有元素),last指针也指向新节点...对于前者,仍然只需要新建一个Node和改变前后指针指向,而后者会发生数组复制,将原数组所有元素拷贝到自己从第二个位开始,长度为size的对应位置,然后将入参赋值给0号位置,出了数组复制,还可能出现扩容,
前言 今天在学习集合分支List的特有迭代器ListIterator时遇到两个疑惑,这是第一个,由于角度比较奇怪,教学视频里也没有提及,在和度娘一番攀谈交心后,我仍是一知半解,但这么巧的是,在第二个疑惑中我找到了它们的共通之处...这里先为大家引入一下ListIterator的常用方法 E next():返回迭代中的下一个元素 boolean hasNext():如果迭代具有更多元素,则返回true E previous():返回列表中的上一个元素...hasPrevious()这两个方法,根据方法描述,我们很容易理解为就是 从集合的最后一位开始返回前一个元素 以及 从最后一位开始判断前面是否存在元素,于是在测试学习这个方法时我写出了这样的代码 以下附上代码及图示..."Java" "World" "Hello" 这三个字符串,可预想的事物总是美好的,现实是残酷的哈哈哈,看如下运行图~ 分析问题 在学习过程中,使用E next()和boolean hasNext...()来进行同样的操作是可以正常依次输出 "Hello" "World" "Java" 这三个字符串的 import java.util.ArrayList; import java.util.List;
基于双向链表实现的方式使得 LinkedList 在插入和删除时更优于 ArrayList,而随机访问则比 ArrayList 逊色些。 但也是线程不安全 LinkList UML类图 ?...this.next = next; this.prev = prev; } } void add(int index, E element) 指定的位置插入指定的元素...first = next; } else { //当前结点的, 前面结点的后续指针 更新为当前结点的后续指针 prev.next...{ //当前结点的, 后面结点的前驱指针 更新为当前结点的后续指针 next.prev = prev; x.next...//这里传递了一个0值 return listIterator(0); } 真正的有作用的方法是 public ListIterator listIterator(
; Node prev; Node(Node prev, E element, Node next) { this.item = element...; this.next = next; this.prev = prev; } } //首元素...e final Node l = last; //将链表中的last节点给l,如果是第一个元素的话l为null final Node newNode...增强for循环起始底层也是用迭代器完成的 用debug查看增强for循环,会发现,执行的下一步还是会进到iterator里 listirerator 加入字符串,比如我们想想要在代码中遍历到cc后新增一个...如何解决:事情让一个迭代器做,新迭代器:listiterator,迭代和添加操作都用listiterator来操作 ListIterator iterator = list.listIterator
、Vector 一、List集合 关于List集合的介绍与方法,可参考第一篇文章 「 深入浅出 」java集合Collection和Map 迭代方法ListIterator 相对于其它集合,List集合添加了一种新的迭代方法...next; //结点前指针 java.util.LinkedList.Node prev; Node(java.util.LinkedList.Node... prev, E element, java.util.LinkedList.Node next) { this.item = element;...this.next = next; this.prev = prev; } } } LinkedList的常用方法只做简单介绍不贴源码,具体可自行看源码...LinkedList的Node对象节点; 2.增加该Node节点的前后引用,即该Node节点的prev、next属性,让其分别指上、下节点; 3.修改该Node节点的前后Node节点中pre/next属性
this.prev = prev; } } 3.2.1 成员变量 里面的成员变量主要有三个,之所以记录同时记录头节点和尾节点,主要是为了能够更快的插入以及查找数据。...x.prev = null; x = next; } // 第一个元素和最后一个元素置空 first =...= 0; } 指定index,插入一个集合,和前面不一样的地方在于复制之前,需要计算往后面移动多少位,不是用for循环去插入,而是一次性移动和写入。...Itr属于公共的迭代器,继承它的有ListIterator和PrimitiveIterator。...中文就是:因为Java 5可以用更特定的返回类型(称为协变返回类型)重写方法。但是ListIterator是在Java 1.2中引入的。
迭代器返回的iterators 和 listIterator方法会造成fail-fast机制:如果链表在生成迭代器之后被结构化的修改了,除了使用iterator独有的remove方法外,都会抛出并发修改的异常...因此,在面对并发修改的时候,这个迭代器能够快速失败,从而避免非确定性的问题 二、LinkedList 继承接口和实现类介绍 java.util.LinkedList 继承了 AbstractSequentialList...System.out.println(listIterator.previous()); } } }输出:-------1------- [top...(Node prev, E element, Node next) { this.item = element; this.next = next...氛围 文章参考: Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例 java双向链表示意图
由于LinkedList实现了List接口,因此还需要实现List接口中的抽象方法,这里就不一一列出了。2....; this.next = next; this.prev = prev; }} 每个节点包含三个属性:item表示节点存储的元素,next表示下一个节点,prev表示上一个节点...= x.next; final Node prev = x.prev; if (prev == null) { first = next; } else {...prev.next = next; x.prev = null; } if (next == null) { last = prev; } else {...测试代码分析 根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。这是一个使用Java中的LinkedList类进行操作的示例代码。
Java集合主要由2大体系构成,分别是Collection体系和Map体系,其中Collection和Map分别是2大体系中的顶层接口。... next; //结点前指针 java.util.LinkedList.Node prev; Node(java.util.LinkedList.Node...this.next = next; this.prev = prev; } } } add() LinkedList的添加方法,主要分为2种,一是直接添加一个元素... next = x.next; //获取被删除元素的前指针结点: final java.util.LinkedList.Node prev = x.prev; //...{ //前置结点的 尾结点指向被删除的next结点; prev.next = next; //被删除结点前指针置为null: x.prev
last = pred; // 否则就维护最后一个元素和之前的元素之间的关系 } else { pred.next = succ; succ.prev = pred; }...,next为first if (prev == null) { first = next; // 否则 prev的下一个元素为x的next } else { prev.next...= next; // 设为null,方便prev的GC x.prev = null; } // 同上 if (next == null) { last = prev...; } else { next.prev = prev; // 设为null,方便next的GC x.next = null; } // 设为null,方便GC...引用Java编程思想里的话: 最佳的做法可能是将ArrayList作为默认选择,只有你需要使用额外的功能(个人理解为对Queue的操作),或者当程序的性能因为经常从表中间进行插入和删除而变差的时候,才去选择
领取专属 10元无门槛券
手把手带您无忧上云