List集合之LinkedList(三)LinkedList总结,前端开发自学教程

public static void testConstructor(){

LinkedList linkedList = new LinkedList©;

System.out.println(linkedList);

LinkedList linkedList1 = new LinkedList();

System.out.println(linkedList1);

/**

  • 构造器测试结果:

  • 无参构造器创建的是一个空集合

  • 带参构造器创建的是一个将参数c集合元素,按照c.toArray()后数组元素的顺序一一加入到LinkedList集合中。

  • 无参构造器创建的集合对象的first,last节点都为null,size=0;

  • 有参构造器创建的集合对象的first,last取决于c集合的首元素和尾元素,size取决去c集合的元素个数。

*/

}

public static void testMethodFromList(){

LinkedList linkedList = new LinkedList();

// add(E e)

// 该方法是将e元素插入到LinkedList尾部

// 内部实现:

// 0.记录last节点 即 Node copyOldLast = last;

// 1.创建新节点 即Node newNode = new Node(copyOldLast,e,null)

// 2.变更last指向 即 last = newNode

// 3.判断copyOldLast是否为null,

// 若copyOldLast为null,则说明原链表是空链,则newNode是唯一节点,即first也要指向newNode

// 若copyOldLastb不为null,则说明原链表不是空链,则copyOldLast.next指向需要从null改为指向newNode

// 5.size++ 即集合元素个数加1

// 6.modCount++ 即 集合结构化修改次数加1

linkedList.add(0);

linkedList.add(1);

linkedList.add(2);

linkedList.add(3);

linkedList.add(4);

// get(int index)

// 该方法用于获取集合index索引处的节点的元素

// 内部实现:

// 1.由于LinkedList底层数据结构链表节点没有索引,但是节点是由顺序的,且是双向顺序

// 所以LinkedList内部将头节点视为索引0,尾节点视为索引size-1,中间按顺序一次索引加1

// 2.内部如何查找索引位置,由于链表维护上一步中的索引,所以无法实现随机访问,必须顺序访问实时计算链表节点的索引

// 即每次获取某索引的节点,都要从first节点开始重新计算索引(+1),或者last节点考试重新计算索引(-1)

// 3.如何实现计算链表节点索引

// 我们知道 first的索引是0,first的下一个节点的索引是1,first的下下个节点的索引是2,…,last的所有是size-1

// 用for循环遍历的话, 即

// 由于最终要获得某索引的节点的item,所以遍历得到节点即可。且初始条件中 节点是first

// 即 Node node = first

// for(int i=0;i<index;i++) node = node.next;

// 另外为了提升效率,采用了二分法查询,即 index<size/2时,采用Node node = first

// index>=size/2时,采用Node node = last,且 for(int i=size;i>index;i–) node = node.prev

linkedList.get(2);

// add(int index,E e)

// 该方法是将e插入到LinkedList集合的index索引处

// 内部实现:

// 1.判断插入索引index是否合法,即只能插入到底层链表的头(索引0),尾部(索引size),中间(0~size-1)

// 即 0 <= index <= size

// 否则抛出索引越界异常,如下

// linkedList.add(6,5);//java.lang.IndexOutOfBoundsException: Index: 6, Size: 5

// 2.当索引index合法时,将index位置的节点取出来备份

// 即 Node copyIndexNode = node(index); 关于node(int index)方法会在就是get方法的逻辑

// 3.创建新节点

// 3.1.如果index=0,那么copyIndexNode就是头节点,则newNode插入后,newNode就是头节点。即first=newNode;newNode.prev=null,newNode.next=copyIndexNode

// 3.2.如果index=size,那copyIndexNode就是null,则newNode插入后,newNode就是尾节点,即last=newNode,newNode.prev=copyIndexNode,newNode.next=null

// 3.3.如果0<index<size,那么 newNode = new Node(copyIndexNode.prev,e,copyIndexNode);

// 4. size++

// 5. modCount++

linkedList.add(5,5);

// add(Collection c)

// 该方法是将c集合中元素按迭代器迭代顺序(但不一定使用迭代器迭代)插入到LinkedList集合尾部

// 1.将c集合转为数组 即 Object[] arr = c.toArray()

// 2.判断c集合是否为空集合,即arr.length==0?返回false:继续下一步

// 3.遍历arr数组元素

// 3.1 创建遍历元素的节点,即 Node newNode0 = new Node(last,arr[0],null)

// 3.2 创建遍历元素的节点,即 Node newNode1 = new Node(newNode0,arr[1],null),且newNode0.next=newNode1

// 3.3按照3.2的逻辑重复操作到arr元素遍历完

// 4. size+=arr.length 即集合元素个数增加了c集合元素个数个

// 5. modCount++ 即集合结构化修改次数+1

linkedList.addAll©;

// add(int index,Collection c)

// 该方法时将c集合中元素按迭代器迭代顺序(但不一定使用迭代器迭代)插入到LinkedList集合的index位置

// 该方法的实现逻辑就是 add(int index,E e)和add(Collection c)两个方法结合

linkedList.addAll(1,c);

//System.out.println(linkedList);//[0, A, B, C, D, 1, 2, 3, 4, 5, A, B, C, D]

// remove()

// 该方法就是删除LinkedList集合头元素。

// 内部实现:

// 1.判断链表是否为空链表,若为空链表则抛出无此元素异常

// new LinkedList().remove();//java.util.NoSuchElementException

// 2.若底层链表不是空链表,则删除该链表的头节点

// 2.1 如果该链表只有一个节点,则这个唯一节点既是头节点,也是尾节点

// 即删除了该节点,链表就为空链表,即first=null,last=null

// 2.2 如果底层链表有多个节点,则

// 2.2.1 备份头节点:Node copyFirNode = first;

// 2.2.2 由于要删除头节点,所以头节点后一个节点就是新的头节点,即first = copyFirNode.next; first.prev = null;

// 2.2.3 断开copyFirNode和新的first节点的联系,即copyFirNode.next = null

// 2.2.4 彻底删除copyFirNode,此时copyFirNode的prev,next都是null,所以只要将copyFirNode.item=null,该元素就是真正的垃圾了

// 3. size–

// 4. modCount++

linkedList.remove();

// remove(int index)

// 该方法表示删除指定索引处的集合元素

// 内部实现

// 1.判断index是否合法,即 0<=index<=size-1,因为集合元素的索引只在0~size-1

// 2.获取index位置的节点,并备份该节点。即 Node copyIndexNode = node(index);

// 3.获取该节点的前后节点并保存:Node BeforeIndexNode = copyIndexNode.prev; Node AfterIndexNode = copyIndexNode.next;

// 4.删除index索引处的节点:即 copyIndexNode.prev=null,copyIndexNode.next=null,copyIndexNode.item=null

// 5.建立BeforeIndexNode,AfterIndexNode之间的联系

// 5.1 如果BeforeIndexNode==null,AfterIndexNode!=null,

// 则说明被删除的copyIndexNode是头节点,则AfterIndexNode现在是新的头节点,即first=AfterIndexNode,AfterIndexNode.prev=null

// 5.2 如果BeforeIndexNode!=null,AfterIndexNode==null

// 则说明被删除的copyIndexNode是尾节点,则BeforeIndexNode现在是新的尾节点,即last=BeforeIndexNode,BeforeIndexNode.next=null

// 5.3 如果BeforeIndexNodenull,AfterIndexNodenull,

// 则说明被删除的copyIndexNode是唯一节点,即现在是空链表,即first=null,last=null

// 5.4 如果BeforeIndexNode!=null,AfterIndexNode!=null,

// 则需要 BeforeIndexNode.next = AfterIndexNode ; AfterIndexNode.prev = BeforeIndexNode

linkedList.remove(4);

// remove(Object o)

// 该方法用于删除和o相同的第一个集合元素

// 当o==null时,o无法使用equals,所以删除集合中第一个节点的item为null的节点

// 当o!=null时,o使用equals去比较集合元素,删除第一个结果为true的元素所在节点

linkedList.remove(“A”);

// clear()方法用于清空集合元素

// 内部实现:

// 1.遍历循环链表节点,将每个节点的prev,item,next设置为null

// 2.将first,last设置为null

// 3.将size=0

// 4.modCount++

//linkedList.clear();

// set(int index,E e)

// 该方法用于将集合元素索引位置1的节点的item改为e

// 内部实现,先判断index是否合法,即0<=index<size,再获取index处节点node(index),并修改node(index).item=e

linkedList.set(1,“F”);

// indexOf(Object o)用于获取o元素再集合中首次出现的位置索引

// lastIndexOf(Object o)用于获取o元素在集合中末次出现的位置索引

// 这两个方法本质也是遍历链表节点,找到和o相同的元素,只是indexOf是从首到尾遍历,lastIndexOf是从尾到首遍历

// 比较时,o如果是null,采用==,o如果是非null,采用equals

// 上述两个方法当找不到对应元素时返回-1

linkedList.indexOf(“B”);

linkedList.lastIndexOf(“B”);

// contains(E e)用于判断集合中是否包含e

// 内部实现:return indexOf(o) != -1

linkedList.contains(“B”);

// size()用于返回集合元素个数

// 即 return size;

linkedList.size();

// toArray()用于将集合转为Object[]数组

// 内部实现:

// 1.先创建一个长度为size的Object[]数组

// 2.遍历LinkedList底层链表的节点,并取出节点的item存入数组中

linkedList.toArray();

// toAarry(T[] a)用于将集合转成T[]数组

// 当形参a数组的长度小于size时,创建一个T[]类型的长度为size的新数组

// 当形参a数组的长度大于size时,则将大于size部分的索引元素设为null

// 遍历链表,将集合元素存入数组0~size-1索引中。

linkedList.toArray(new Object[0]);

}

public static void testMethodFromObject(){

LinkedList linkedList = new LinkedList();

Person p1 = new Person(“qfc”,18);

Person p2 = new Person(“zyx”,19);

Person p3 = new Person(“swk”,20);

Person p4 = new Person(“zbj”,21);

Collections.addAll(linkedList,p1,p2,p3,p4);

System.out.println(linkedList.get(0));

/**

  • 由于LinkedList实现了Cloneable接口,且重写clone方法,在clone方法中调用了super.clone(),获得对象拷贝

  • 后面将拷贝对象的first,last设为null,将size,modCount设为null

  • 然后遍历被拷贝对象的节点,将节点中的item取出,通过cloneObject.add(item);给克隆对象插入对应元素

  • 为什么不直接使用super.clone()结果呢?因为这样会导致 拷贝对象的first,last 和 被拷贝对象的first,last 指向同一个内存上节点,这实际上已经不算对象克隆了。

*/

LinkedList clone = (LinkedList)linkedList.clone();

Person person = (Person) clone.get(0);

person.setName(“sg”);

person.setAge(12);

System.out.println(linkedList.get(0));

/**

  • 说明:LinkedList的对象克隆是浅克隆

*/

}

public static void testMethodFromDeque(){

LinkedList linkedList = new LinkedList©;

System.out.println(linkedList);

//下面几个方法都是见名知意的

linkedList.addFirst(“A-”);//[A-,A, B, C, D]

linkedList.addLast(“Z”);//[A-,A, B, C, D, Z]

linkedList.removeFirst();//[A, B, C, D, Z]

linkedList.removeLast();//[A, B, C, D]

linkedList.removeFirstOccurrence(“A”);//[B, C, D]

linkedList.removeLastOccurrence(“B”);//[C, D]

//下面几个方法是模拟顺序栈的操作

linkedList.push(“A-”);//[A-,C, D]

linkedList.peek();//[A-,C, D]

linkedList.pop();//[C, D]

System.out.println(linkedList);//[C, D]

//下面几个方法是模拟双向栈的操作

//注意offer()是栈底压栈

linkedList.offer(“A–”);//[C, D, A–]

linkedList.offerFirst(“A-”);//[A-, C, D, A–]

linkedList.offerLast(“Z”);//[A-, C, D, A–, Z]

linkedList.peekFirst();//[A-, C, D, A–, Z]

linkedList.peekLast();//[A-, C, D, A–, Z]

linkedList.poll();//[C, D, A–, Z]

linkedList.pollFirst();//[D, A–, Z]

linkedList.pollLast();//[D, A–]

System.out.println(linkedList);

//取出栈顶元素

Object element = linkedList.element();//D

System.out.println(element);

}

public static void testIterator(){

LinkedList linkedList = new LinkedList©;

// iterator()本质是调用的LinkedList的listIterator(0);

// 所以该方法本质是返回一个ListIterator对象

Iterator iterator = linkedList.iterator();

ListIterator listIterator = (ListIterator) iterator;

boolean hasPrevious = listIterator.hasPrevious();

System.out.println(hasPrevious);//由于该迭代器本质是listIterator(0),所以next为node(0),所以nextIndex=0,而hasPrevious内部是要求 nextIndex>0

boolean hasNext = listIterator.hasNext();

System.out.println(hasNext);//hasNext()本质就是要求 nextIndex<size

listIterator.next();

listIterator.next();

listIterator.next();

listIterator.next();

System.out.println(listIterator.hasNext());

System.out.println(listIterator.hasPrevious());

listIterator.previous();

listIterator.previous();

listIterator.nextIndex();

listIterator.previousIndex();

/**

  • 到目前为止,以证明了LinkedList的iterator()方法,该方法虽然返回的是Iterator实现类对象,但实质是ListIterator实现类对象

  • 因为Iterator实现类对象没有previous(),hasPrevious(),nextIndex(),previousIndex()方法

  • 其他set,add方法就先不在此处演示

*/

}

public static void testListIterator(){

/**

  • LinkedList有两种方式直接获取ListIterator实现类对象

  • 1.ListIterator listIterator();

  • 2.ListIterator listIterator(int index);

  • 其中1的内部实现就是调用了2的listIterator(0);这里不演示listIterator()

*/

LinkedList linkedList = new LinkedList©;

ListIterator listIterator = linkedList.listIterator(4);

while (listIterator.hasPrevious()){

System.out.println(listIterator.previous());

}

System.out.println(“====================================”);

System.out.println(listIterator.nextIndex());

System.out.println(listIterator.previousIndex());

System.out.println(“====================================”);

while(listIterator.hasNext()){

System.out.println(listIterator.next());

}

System.out.println(“====================================”);

System.out.println(listIterator.nextIndex());

System.out.println(listIterator.previousIndex());

System.out.println(“====================================”);

listIterator.add(“E”);

System.out.println(linkedList);

System.out.println(“====================================”);

// 注意add操作后,lastReturned被重置为null,而remove操作时删除lastReturned索引上节点,所以该处remove操作会抛出非法状态异常

// listIterator.remove();//java.lang.IllegalStateException

listIterator.previous();

listIterator.remove();

System.out.println(linkedList);

System.out.println(“====================================”);

// 注意remove操作后,lastReturned被重置为null,而set操作是修改lastReturned索引上的节点的item,所以该处set操作会抛出非法状态异常

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

img
img

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip1024c 备注前端获取(资料价值较高,非无偿)
img

文末

逆水行舟不进则退,所以大家要有危机意识。

同样是干到35岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。

这也是为什么大家都说35岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。

为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师核心知识笔记》电子稿文件。

内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。

269页《前端大厂面试宝典》

包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端面试题汇总

义、实战项目、讲解视频,并且后续会持续更新**
如果你觉得这些内容对你有帮助,可以添加V:vip1024c 备注前端获取(资料价值较高,非无偿)
[外链图片转存中…(img-bnlaVQxD-1711570552188)]

文末

逆水行舟不进则退,所以大家要有危机意识。

同样是干到35岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。

这也是为什么大家都说35岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。

为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师核心知识笔记》电子稿文件。

内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。

269页《前端大厂面试宝典》

包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端面试题汇总

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: LinkedListJava集合类之一,是一个双向链表。它特有的方法包括: 1. addFirst(E e):将指定元素插入此列表的开头。 2. addLast(E e):将指定元素插入此列表的结尾。 3. getFirst():返回此列表的第一个元素。 4. getLast():返回此列表的最后一个元素。 5. removeFirst():移除并返回此列表的第一个元素。 6. removeLast():移除并返回此列表的最后一个元素。 7. offerFirst(E e):在此列表的开头插入指定的元素。 8. offerLast(E e):在此列表的结尾插入指定的元素。 9. pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回 null。 10. pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回 null。 ### 回答2: ListJava集合类中常用的一种,而LinkedListList集合中的一种实现,和ArrayList相比,它具有一些独特的方法。 首先,LinkedList支持在list开头和结尾添加元素的方法。即addFirst(E e)和addLast(E e)。这两个方法在其他List实现中是没有的。这对于链表来说非常方便,因为在链表中,添加元素时只需要修改指针的指向即可,而不用像数组一样需要移动其他元素。 其次,LinkedList支持获取链表的头部和尾部元素的方法。即getFirst()和getLast()。同样,其他List实现中也没有这种方法,这也是LinkedList适合做队列和栈这种数据类型的原因之一。 除了这些独有的方法之外,LinkedList还具有一些其他List实现也有的方法。例如remove(int index)和size()方法就是常规List接口所具有的。LinkedList还实现了Queue和Deque接口,使得LinkedList也可以充当队列和双端队列。 需要注意的一点是,由于LinkedList是链表的形式,所以访问其中的元素时速度比较慢。因此,在需要随机访问元素的情况下,最好使用ArrayList。但是,当需要频繁在开头和结尾添加或删除元素时,LinkedList则具有明显的优势。 总之,LinkedListList集合中的一种实现,它具有一些独特的方法,如addFirst,getFirst等方法。同时,它也可以作为队列、栈、双端队列等数据结构的实现。但是在需要随机访问元素的情况下,建议使用其他List实现,如ArrayList。 ### 回答3: Java集合类是Java编程中常用的工具之一,List是其中一种很重要的集合类。LinkedListList的一种实现方式,LinkedList在插入和删除数据方面比较快。本文将会介绍LinkedList的特有方法的使用。 LinkedList继承了AbstractSequentialList,也实现了List、Deque、Cloneable、Serializable接口。由于LinkedList的底层实现是双向链表,因此它具有插入和删除元素效率高的特点。 下面是LinkedList特有的方法: 1. public void addFirst(E e),将指定元素添加到此列表的开头: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.addFirst("C++"); System.out.println(linkedList); // [C++, Java, Python] 2. public void addLast(E e),将指定元素添加到此列表的结尾: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.addLast("C++"); System.out.println(linkedList); // [Java, Python, C++] 3. public E removeFirst(),删除并返回此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.removeFirst(); System.out.println(first); // Java System.out.println(linkedList); // [Python, C++] 4. public E removeLast(),删除并返回此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.removeLast(); System.out.println(last); // C++ System.out.println(linkedList); // [Java, Python] 5. public E getFirst(),返回此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.getFirst(); System.out.println(first); // Java 6. public E getLast(),返回此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.getLast(); System.out.println(last); // C++ 7. public E peekFirst(),获取但不移除此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.peekFirst(); System.out.println(first); // Java System.out.println(linkedList); // [Java, Python, C++] 8. public E peekLast(),获取但不移除此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.peekLast(); System.out.println(last); // C++ System.out.println(linkedList); // [Java, Python, C++] 9. public boolean offerFirst(E e),将指定元素插入此列表的开头: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); boolean result = linkedList.offerFirst("C++"); System.out.println(result); // true System.out.println(linkedList); // [C++, Java, Python] 10. public boolean offerLast(E e),将指定元素插入此列表的结尾: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); boolean result = linkedList.offerLast("C++"); System.out.println(result); // true System.out.println(linkedList); // [Java, Python, C++] LinkedList是一个非常实用的Java集合类,我们可以根据自己的需求选择使用其中的特有方法。在实际开发中,结合List可以方便地实现队列和栈的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值