seo华为网站诊断报告提供营销型网站设计
seo华为网站诊断报告,提供营销型网站设计,爱站网关键词密度查询,百度网盘怎么找片上一篇文章LinkedList实现分析(一)——LinkedList初探与对象创建介绍了LinkedList中的一些重要属性和构造方法#xff0c;下面我们将详细介绍一下LinkedList提高的常用方法的实现原理元素添加###add(E e)方法往LinkedList添加元素#xff0c;LinkedList提供了多重方式#x…上一篇文章LinkedList实现分析(一)——LinkedList初探与对象创建介绍了LinkedList中的一些重要属性和构造方法下面我们将详细介绍一下LinkedList提高的常用方法的实现原理元素添加###add(E e)方法往LinkedList添加元素LinkedList提供了多重方式首先介绍add方法下面我们使用一个简单的实例代码来分析一下add方法的实现原理List myList new LinkedList();//1myList.add(a); //2myList.add(b); //3myList.add(c); //4执行第一行代码后创建了一个空的myList对象此时myList如下图所示myList然后执行第2行代码myList.add(a)把字符串a添加到myList中通过debug方式进入add方法内部public boolean add(E e) { linkLast(e); return true;}add又调用linkLast方法linkLast方法实现如下void linkLast(E e) { final Node l last; final Node newNode new Node(l, e, null); last newNode; if (l null) first newNode; else l.next newNode; size; modCount;}在linkLast内部此时ea。首先把last此时myList是新创建的对象lastnull赋值给一个临时变量 l这里的做法是用来保存last的值然后用元素e创建一个新的Node对象这里是往myList的尾部添加元素因此创建的Node节点的构造方法最后一个参数是null而第一个参数表示的是插入元素e的前一个元素指针因此需要传入l因为在整个LinkedList中last属性表示的最后一个元素。当创建好包含e的newNode节点的时候此时newNode就应该是myList的最后一个节点也是第一个节点(lnull)因此把newNode赋值给last和first然后把表示myList大学的size进行加一最后对modCount加一记录了修改次数。执行完第2行代码后myList的状态入下图所示:myList当示例代码执行第3行代码的时,同样会执行linkLast此时e“b”。在进入linkLast方法的时候last的值已经不在是null而是刚刚创建的包含了“a”的Node节点对象同样把last先用一个临时变量l保存起来然后创建一个包含“b”的Node节点这个时候该node节点的前一个节点是“a”所在的节点因此构造函数 new Node(l, e, null)把新创建的newNode作为整个myList的最后一个节点 last newNode而由于l不为null也就是last不为null所以需要把新创建的节点放到myList中最后一个节点的后面 l.next newNode最后修改size和modCount的值完成“b”元素的添加。此时myList的状态如下图所示然后示例代码执行到第4行此时myList已经有2个node根据上图可知last指向了“b”node然创建“c”的node对象让“c”的prev执行“b”然后myList中的last指向“c”“b”的next执行“c”执行完后myList的状态如下图所示:### add(int index, E element)该方法是在指定的索引的位置插入一个元素index值指定的索引位置element是需要插入的元素信息。这里还是以一个示例为基础进行对 add(int index, E element) 源码的分析示例代码如下List myList new LinkedList();//1myList.add(a); //2myList.add(0,b)//3当示例代码执行完第2部的时候myList的状态如下图所示然后执行第3行代码具体 add(int index, E element) 的源码如下public void add(int index, E element) { checkPositionIndex(index);//index校验 if (index size) linkLast(element); else linkBefore(element, node(index));}首先是对传入的index进行位置校验具体实现是要求index不能小于0不能大于myList当前的大小。根据示例代码执行到第3行的时候此时size1index0因此程序执行linkBefore方法linkBefore是第一参数是新添加的元素element第二个参数表示element需要被添加到myList中哪个元素的后面。这里传入是位置索引因此需要调用node(index)方法找到mylist中index对应的node对象node方法实现如下Node node(int index) { if (index (size 1)) { Node x first; for (int i 0; i index; i) x x.next; return x; } else { Node x last; for (int i size - 1; i index; i--) x x.prev; return x;}这里源码中使用了一个技巧通过判断传入的index与整个list的大小(size)的1/2进行比较如果indexsize/2那么对myList进行倒序遍历。这里需要大家注意的是源码中使用右移操作获取size的1/2这个技巧希望大家可以掌握在java中数字左移表示乘2数字右移除2由于当前myList的size1右移之后是0index0因此执行else的语句从last指向的node开始倒序遍历此时myList只有一个index0所指向的元素就是last的值因此把last返回。node方法执行完之后开始执行linkBefore方法void linkBefore(E e, Node succ) { final Node pred succ.prev; final Node newNode new Node(pred, e, succ); succ.prev newNode; if (pred null) first newNode; else pred.next newNode; size; modCount;}linkBefore方法就是一个双向列表的插入操作首先把succ的前驱节点prev保存到临时变量pred使用传入的e(根据示例代码此时e“b”)创建一个新的Node对象newNode由于是在succ节点的前面插入新元素b因此newNode的前驱点是之前succ节点的前驱节点newNode的后节点就是succ节点本身final Node newNode new Node(pred, e, succ)此时myList的状态如下图所示然后执行 succ.prev newNode是把原来succ指向的前驱节点改成了newNode因为newNode插入了succ节点前面因此succ的prev就是newNode指向完的myList状态如下然后是判断pred是否为null,在myList的当前状态中 succ.prev是nullpred也就是null所以把first指向newNode也就是在myList的头结点succ之前添加一个新元素newNode即 first newNode;然后对size和modCount加一执行完最后myList的状态如下图:### addAll(Collection extends E c)下面介绍一下使用集合对象给LinkedList添加元素addAll有两个重载方法public boolean addAll(Collection extends E c)public boolean addAll(int index, Collection extends E c)在源码中addAll(Collection extends E c)实际是调用了addAll(int index, Collection extends E c) :public boolean addAll(Collection extends E c) { return addAll(size, c);}因此这里只介绍后面一个addAll的实现: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 pred, succ; if (index size) { succ null; pred last; } else { succ node(index); pred succ.prev; } //把a中的元素创建为一个列表 //并且让pred指向a的最后一个节点 for (Object o : a) { Node newNode new Node(pred, e, null); if (pred null) first newNode; else pred.next newNode; pred newNode; } //如果没有后继节点那么c集合中最后一个节点就是 //整个list的最后节点 if (succ null) { last pred; } else { //如果在list找到插入的前驱和后继节点 //把c中的最后一个节点的后继节点指向succ //把后继节点的前驱节点指向c中的最后一个节点 pred.next succ; succ.prev pred; } size numNew; modCount; return true;}addAll方法内部首先还是判断index的值是否合法然后对传入的Collection对象c进行验证 接着在源码中定义了两个变量Node pred, succ;pred表示需要插入c的前驱节点succ表示c的后继节点。当indexsize表示是把c添加到LinkedList的尾部因此执行succnull和predlast;否则调用 node(index)方法找到后继节点succ然后把当前后继节点的前驱节点赋值给pred。找到所插入前驱和后继节点之后开始循环遍历c把c中的每一个元素创建一个Node对象c中的前一个元素都是后一个元素的前驱节点把c建立为一个链表。然后把c的链表插入的LinkedList中具体见上面源码的注释完成链表的连接操作只会对size和modCount进行加1操作。### 其他添加元素的方法下面介绍一个往list头插入元素的方法public void addFirst(E e) {linkFirst(e);}private void linkFirst(E e) { //保存第一个元素 final Node f first; //头插法因此newNode的前驱节点是null后继节点是f final Node newNode new Node(null, e, f); //让新创建节点当整个list的头节点 first newNode; if (f null) //如果fnull表示当前list没有一个元素因此需要给lastnewNode last newNode; else //把之前的first接的前驱节点换成新创建的newNode f.prev newNode; size; modCount; }头插入的原理就是在整个list中找到一个元素first把first的前驱节点换成新插入的元素然后把新传入元素的后继节点指向之前的头节点具体实现见上面源码和注释LinkedList提供了offer(E e)offerFirst(E e) offerLast(E e)addFirst(E e) addLast(E e)push(E e) 往list中添加一个元素的方法这些方法的底层都是基于上面介绍的原理实现的头插和尾插。这里就不多做说明。获取元素LinkedList获取元素提供多种方法//根据索引获取元素public E get(int index)//获取头元素public E peek()//获取头元素并且把头元素从list中删除public E poll()//获取头元素并且把头元素从list中删除public E pop()下面追个介绍这些方法的具体实现public E get(int index) {checkElementIndex(index);return node(index).item;}由上面源码可知get操作底层是调用的node方法node方法参考上面的介绍。下面是peekpeek操作是获取头元素因此只需要获取到LinkedList的first所执行的元素就可以了。public E peek() {final Node f first;return (f null) ? null : f.item;}下面介绍poll():public E poll() { final Node f first; return (f null) ? null : unlinkFirst(f);}private E unlinkFirst(Node f) { //保存f的具体值 final E element f.item; final Node next f.next; f.item null; f.next null; // help GC //f的后继节点赋值给LinkedList的first first next; //nextnull表示要删除的节点是list的最后一个节点 if (next null) last null; else //表示删除f之后的list列表中头结点的prev应该为null而之前 //prev是执行f的 next.prev null; size--; modCount; return element; }由上面源码可知当调用poll的时候会把LinkedList的头元素返回然后把头元素从LinkedList中删除。下面看一下pop方法public E removeFirst() {final Node f first;if (f null) throw new NoSuchElementException();return unlinkFirst(f);}pop方法的底层也是调用unlinkFirst方法完成头结点的删除操作。##To Array的操作LinkedList提供了两种方法完成list到数组的转换public Object[] toArray()public T[] toArray(T[] a)第一个方法是把list转为Object类型的数组具体是实现如下public Object[] toArray() { Object[] result new Object[size]; int i 0; for (Node x first; x ! null; x x.next) result[i] x.item; return result; }该方法的实现原理比较简单首先创建一个大小与list相同的object类型数组然后从头到尾遍历list的元素把每个元素放到创建的数组中因为数组对象是Object类型因此list中的任何元素都可以直接放入到数组中最后把数组返回。在T[] toArray(T[] a) 方法中需要传递一个T类型的数组对象这样可以按照T类型返回T类型数组public T[] toArray(T[] a) { if (a.length size) a (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); int i 0; Object[] result a; for (Node x first; x ! null; x x.next) result[i] x.item; if (a.length size) a[size] null; return a;}首先是判断传入的数组a的大小是否大于或者等于list的大小如果小于那么利用反射机制重新创建一个数组此时参数a和toArray的数组就不是同一个数组了如果a的大小大于size的值假设数组a{1
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/90456.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!