【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. }
相关推荐
yylの博客2 小时前
Windows通过git-bash安装zsh
windows·git·bash·zsh
进击的code2 小时前
windows 下使用WLS2 编译aosp Android14并刷机到pixle 5a
windows
禁默2 小时前
2024年图像处理、多媒体技术与机器学习
图像处理·人工智能·microsoft
染指11105 小时前
50.第二阶段x86游戏实战2-lua获取本地寻路,跨地图寻路和获取当前地图id
c++·windows·lua·游戏安全·反游戏外挂·游戏逆向·luastudio
Zmxcl-0076 小时前
IIS解析漏洞
服务器·数据库·microsoft
dntktop6 小时前
Converseen:全能免费批量图像处理专家
windows
一个懒鬼8 小时前
Windows脚本清理C盘缓存
windows·缓存
蚁景网络安全9 小时前
Cobalt Strike 4.8 用户指南-第十四节 Aggressor 脚本
windows·microsoft
Camllia379 小时前
电脑运行库DirectX出问题怎么办?
windows·经验分享·电脑
总是学不会.10 小时前
【集合】Java 8 - Stream API 17种常用操作与案例详解
java·windows·spring boot·mysql·intellij-idea·java集合