【Java】LinkedList实现类的使用

LinkedList实现类的使用
  1. package com.star.test04;
  2. import java.util.Iterator;
  3. import java.util.LinkedList;
  4. /**
  5. * @author : Starshine
  6. */
  7. public class Test {
  8. //这是main方法,程序的入口
  9. public static void main(String[] args) {
  10. /*
  11. LinkedList常用方法:
  12. 增加 addFirst(E e) addLast(E e)
  13. offer(E e) offerFirst(E e) offerLast(E e)
  14. 删除 poll()
  15. pollFirst() pollLast() ---》JDK1.6以后新出的方法,提高了代码的健壮性
  16. removeFirst() removeLast()
  17. 修改
  18. 查看 element()
  19. getFirst() getLast()
  20. indexOf(Object o) lastIndexOf(Object o)
  21. peek()
  22. peekFirst() peekLast()
  23. 判断
  24. */
  25. //创建一个LinkedList集合对象:
  26. LinkedList<String> list = new LinkedList<>();
  27. list.add("aaaaa");
  28. list.add("bbbbb");
  29. list.add("ccccc");
  30. list.add("ddddd");
  31. list.add("eeeee");
  32. list.add("bbbbb");
  33. list.add("fffff");
  34. list.addFirst("jj");
  35. list.addLast("hh");
  36. list.offer("kk");//添加元素在尾端
  37. list.offerFirst("pp");
  38. list.offerLast("rr");
  39. System.out.println(list);//LinkedList可以添加重复数据
  40. System.out.println(list.poll());//删除头上的元素并且将元素输出
  41. System.out.println(list.pollFirst());
  42. System.out.println(list.pollLast());
  43. System.out.println(list.removeFirst());
  44. System.out.println(list.removeLast());
  45. System.out.println(list);//LinkedList可以添加重复数据
  46. /*list.clear();//清空集合
  47. System.out.println(list);*/
  48. /*System.out.println(list.pollFirst());*/
  49. /*System.out.println(list.removeFirst());报错:Exception in thread "main" java.util.NoSuchElementException*/
  50. //集合的遍历:
  51. System.out.println("---------------------");
  52. //普通for循环:
  53. for(int i = 0;i<list.size();i++){
  54. System.out.println(list.get(i));
  55. }
  56. System.out.println("---------------------");
  57. //增强for:
  58. for(String s:list){
  59. System.out.println(s);
  60. }
  61. System.out.println("---------------------");
  62. //迭代器:
  63. /*Iterator<String> it = list.iterator();
  64. while(it.hasNext()){
  65. System.out.println(it.next());
  66. }*/
  67. //下面这种方式好,节省内存
  68. for(Iterator<String> it = list.iterator();it.hasNext();){
  69. System.out.println(it.next());
  70. }
  71. }
  72. }
LinkedList简要底层原理图
模拟LinkedList源码
  1. package com.star.test05;
  2. /**
  3. * @author : Starshine
  4. */
  5. public class MyLinkedList {
  6. //链中一定有一个首节点:
  7. Node first;
  8. //链中一定有一个尾节点:
  9. Node last;
  10. //计数器:
  11. int count = 0;
  12. //提供一个构造器:
  13. public MyLinkedList(){
  14. }
  15. //添加元素方法:
  16. public void add(Object o){
  17. if(first == null){//证明你添加的元素是第一个节点:
  18. //将添加的元素封装为一个Node对象:
  19. Node n = new Node();
  20. n.setPre(null);
  21. n.setObj(o);
  22. n.setNext(null);
  23. //当前链中第一个节点变为n
  24. first = n;
  25. //当前链中最后一个节点变为n
  26. last = n;
  27. }else{//证明已经不是链中第一个节点了
  28. //将添加的元素封装为一个Node对象:
  29. Node n = new Node();
  30. n.setPre(last);//n的上一个节点一定是当前链中的最后一个节点last
  31. n.setObj(o);
  32. n.setNext(null);
  33. //当前链中的最后一个节点的下一个元素 要指向n
  34. last.setNext(n);
  35. //将最后一个节点变为n
  36. last = n;
  37. }
  38. //链中元素数量加1
  39. count++;
  40. }
  41. //得到集合中元素的数量:
  42. public int getSize(){
  43. return count;
  44. }
  45. //通过下标得到元素:
  46. public Object get(int index){
  47. //获取链表的头元素:
  48. Node n = first;
  49. //一路next得到想要的元素
  50. for(int i=0;i<index;i++){
  51. n = n.getNext();
  52. }
  53. return n.getObj();
  54. }
  55. }
  56. class Test{
  57. //这是main方法,程序的入口
  58. public static void main(String[] args) {
  59. //创建一个MyLinkedList集合对象:
  60. MyLinkedList ml = new MyLinkedList();
  61. ml.add("aa");
  62. ml.add("bb");
  63. ml.add("cc");
  64. System.out.println(ml.getSize());
  65. System.out.println(ml.get(0));
  66. }
  67. }

debug验证数据添加成功:

LinkedList源码解析

【1】JDK1.7和JDK1.8的LinkedList的源码是一致的

【2】源码:

  1. public class LinkedList<E>{//E是一个泛型,具体的类型要在实例化的时候才会最终确定
  2. transient int size = 0;//集合中元素的数量
  3. //Node的内部类
  4. private static class Node<E> {
  5. E item;//当前元素
  6. Node<E> next;//指向下一个元素地址
  7. Node<E> prev;//上一个元素地址
  8. Node(Node<E> prev, E element, Node<E> next) {
  9. this.item = element;
  10. this.next = next;
  11. this.prev = prev;
  12. }
  13. }
  14. transient Node<E> first;//链表的首节点
  15. transient Node<E> last;//链表的尾节点
  16. //空构造器:
  17. public LinkedList() {
  18. }
  19. //添加元素操作:
  20. public boolean add(E e) {
  21. linkLast(e);
  22. return true;
  23. }
  24. void linkLast(E e) {//添加的元素e
  25. final Node<E> l = last;//将链表中的last节点给l 如果是第一个元素的话 l为null
  26. //将元素封装为一个Node具体的对象:
  27. final Node<E> newNode = new Node<>(l, e, null);
  28. //将链表的last节点指向新的创建的对象:
  29. last = newNode;
  30. if (l == null)//如果添加的是第一个节点
  31. first = newNode;//将链表的first节点指向为新节点
  32. else//如果添加的不是第一个节点
  33. l.next = newNode;//将l的下一个指向为新的节点
  34. size++;//集合中元素数量加1操作
  35. modCount++;
  36. }
  37. //获取集合中元素数量
  38. public int size() {
  39. return size;
  40. }
  41. //通过索引得到元素:
  42. public E get(int index) {
  43. checkElementIndex(index);//健壮性考虑
  44. return node(index).item;
  45. }
  46. Node<E> node(int index) {
  47. //如果index在链表的前半段,那么从前往后找
  48. if (index < (size >> 1)) {
  49. Node<E> x = first;
  50. for (int i = 0; i < index; i++)
  51. x = x.next;
  52. return x;
  53. } else {//如果index在链表的后半段,那么从后往前找
  54. Node<E> x = last;
  55. for (int i = size - 1; i > index; i--)
  56. x = x.prev;
  57. return x;
  58. }
  59. }
  60. }
面试题:iterator(),Iterator,Iterable关系

【1】面试题:对应的关系:

【2】hasNext(),next()的具体实现:

【3】增强for循环 底层也是通过迭代器实现的:

ListIterator迭代器

【1】加入字符串:

  1. package com.star.test06;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. /**
  6. * @author : Starshine
  7. */
  8. public class Test2 {
  9. //这是main方法,程序的入口
  10. public static void main(String[] args) {
  11. ArrayList<String> list = new ArrayList<>();
  12. list.add("aa");
  13. list.add("bb");
  14. list.add("cc");
  15. list.add("dd");
  16. list.add("ee");
  17. //在"cc"之后添加一个字符串"kk"
  18. Iterator<String> it = list.iterator();
  19. while(it.hasNext()){
  20. if("cc".equals(it.next())){
  21. list.add("kk");
  22. }
  23. }
  24. }
  25. }

发现报错:

出错原因:就是迭代器和list同时对集合进行操作:

解决办法:事情让一个"人"做 --》引入新的迭代器:ListIterator

迭代和添加操作都是靠ListIterator来完成的:

  1. package com.star.test06;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import java.util.ListIterator;
  6. /**
  7. * @author : Starshine
  8. */
  9. public class Test2 {
  10. //这是main方法,程序的入口
  11. public static void main(String[] args) {
  12. ArrayList<String> list = new ArrayList<>();
  13. list.add("aa");
  14. list.add("bb");
  15. list.add("cc");
  16. list.add("dd");
  17. list.add("ee");
  18. //在"cc"之后添加一个字符串"kk"
  19. ListIterator<String> it = list.listIterator();
  20. while(it.hasNext()){
  21. if("cc".equals(it.next())){
  22. it.add("kk");
  23. }
  24. }
  25. System.out.println(it.hasNext());
  26. System.out.println(it.hasPrevious());
  27. //逆向遍历:
  28. while(it.hasPrevious()){
  29. System.out.println(it.previous());
  30. }
  31. System.out.println(it.hasNext());
  32. System.out.println(it.hasPrevious());
  33. System.out.println(list);
  34. }
  35. }
相关推荐
吴声子夜歌4 小时前
Java数据结构与算法——基本数学问题
java·开发语言·windows
薛定谔的猫19827 小时前
Langchain(十二)LangGraph 实战入门:用流程图思维构建 LLM 工作流
数据库·microsoft
这儿有一堆花7 小时前
用原生脚本编写无害恶作剧
windows
因我你好久不见7 小时前
Windows部署springboot jar支持开机自启动
windows·spring boot·jar
夜流冰8 小时前
Excel - MS Support for Excel: 2 Collaborate
数据库·windows·excel
林瞅瞅8 小时前
PowerShell 启动卡顿?内存飙升?原来是 800MB 的历史记录在作祟!
windows
Shepherd06199 小时前
【Windows Server 实战】WAC 反向代理配置
windows
云小逸9 小时前
【windows系统编程】第一章 Windows 系统核心架构与基础概念
windows·架构
怣疯knight11 小时前
Docker Desktop 4.55.0版本安装成功教程
windows·docker
liulilittle12 小时前
VEthernet 框架实现 tun2socks 的技术原理
网络·windows·c#·信息与通信·通信