当前位置: 首页 > article >正文

【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.                
  31.         if (l == null)//如果添加的是第一个节点
  32.             first = newNode;//将链表的first节点指向为新节点
  33.         else//如果添加的不是第一个节点
  34.             l.next = newNode;//将l的下一个指向为新的节点
  35.         size++;//集合中元素数量加1操作
  36.         modCount++;
  37.     }
  38.         //获取集合中元素数量
  39.         public int size() {
  40.         return size;
  41.     }
  42.         //通过索引得到元素:
  43.         public E get(int index) {
  44.         checkElementIndex(index);//健壮性考虑
  45.         return node(index).item;
  46.     }
  47.        
  48.     Node<E> node(int index) {
  49.         //如果index在链表的前半段,那么从前往后找
  50.         if (index < (size >> 1)) {
  51.             Node<E> x = first;
  52.             for (int i = 0; i < index; i++)
  53.                 x = x.next;
  54.             return x;
  55.         } else {//如果index在链表的后半段,那么从后往前找
  56.             Node<E> x = last;
  57.             for (int i = size - 1; i > index; i--)
  58.                 x = x.prev;
  59.             return x;
  60.         }
  61.     }
  62. }
面试题: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. }

http://www.kler.cn/news/367546.html

相关文章:

  • RestHighLevelClient操作es查询文档
  • 质量漫谈一
  • HarmonyOS 相对布局(RelativeContainer)
  • 逻辑回归与神经网络
  • Selenium爬虫技术:如何模拟鼠标悬停抓取动态内容
  • nginx 路径匹配,关于“/“对规则的影响
  • 苹果预告下周发布Mac新品:全系标配M4系列芯片
  • 前端处理API接口故障:多接口自动切换的实现方案
  • bluez hid host介绍,连接键盘/鼠标/手柄不是梦,安排
  • 日常实习与暑期实习详解
  • java使用正则表达式校验字符串pwd,是否符合包含大写小写数字特殊字符长度超过8位
  • Codeforces Round 981 (Div. 3) A - E 详细题解(C++)
  • maven分模块设计与私服
  • 如何用mmclassification训练多标签多分类数据
  • 如何理解前端与后端开发
  • entwine 和 conda环境下 使用和踩坑 详细步骤! 已解决
  • uptime kuma拨测系统
  • 身份证归属地查询接口-在线身份证归属地查询-身份证归属地查询API
  • 论文略读:Less is More: on the Over-Globalizing Problem in Graph Transformers
  • 2FA-双因素认证
  • 基于Python的智能求职分析系统
  • python 使用 企微机器人发送消息
  • 安全日志记录的重要性
  • 今天不分享技术,分享秋天的故事
  • Spring Boot框架下的厨艺社区开发
  • ALLO数据集:首个为月球轨道机器人近距离操作设计的异常检测基准开源数据集。