List子接口LinkedList

LinkedList引入

ArrayList : 底层是数组,通过下标就能查询,它的查询比较快,但是删除比较慢 LinkedList:底层是双向链表,要一个一个的遍历,没有下标,所以数据比较多的时候查询比较 慢,但是它比较适合添加和删除操作。

  • 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高

  • LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末 元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。

LinkeList前置基础知识

单项链表

element:用来存放元素

next:用来指向下一个节点 通过每个节点的指针指向下一个节点从而连接起来的结构,最后一个节点的next指向null

单向循环链表

在单向链表的最后一个节点的next会指向头节点,而不是指向null,这样存成一个环。

双向链表

element:用来存放元素

pre:用来指向上一个节点

next:用来指向下一个节点 双向链表包含两个指针,pre指向前一个节点, next 指向后一个指针,但是第一个节点head(头节点) 的pre指向null,最后一个节点的tail指向null。

双向循环链表

lement、pre、next 跟前面的一样

第一个节点的pre指向最后一个节点,最后一个节点的next指向第一个节点,也形成一个“环”。

LinkedList常用方法

方法名 说明
void addFirst(Object o) 在链表的头部添加元素
void addLast(Object o) 在链表的尾部添加元素
Object getFirst() 获取链表中的第一个元素
Object getLast() 获取链表中的最后一个元素
Object removeFirst 删除中的第一个元素
Object removeLast() 删除链表中的最后一个元素
public static void main(String[] args) {LinkedList linkedList = new LinkedList();linkedList.add("aaa");//添加到数组linkedList.add("bbb");linkedList.add("ccc");linkedList.add("ddd");linkedList.add("eee");System.out.println(linkedList);//打印出添加后的数组//linkedList.clear();linkedList.offerFirst("eee");//在首位添加元素System.out.println(linkedList);linkedList.addFirst("qqq");//继续在首位添加元素System.out.println(linkedList);linkedList.removeFirst();//移除首位元素System.out.println(linkedList);linkedList.pollFirst();//方法检索并删除此列表的第一个元素,如果此列表为空,则返回 nullSystem.out.println(linkedList);}

链表的原理及实现

什么是链表?

链表是由n个子节点组合起来的一种线性数据结构 链表的特性:

  • 链表是以节点(Node)的方式来存储,所以又叫链式存储
  • 节点可以连续存储,也可以不连续存储
  • 节点的逻辑顺序与物理顺序可以不一致
  • 链表可以扩充

单链表

两个部分:

  • data域:数据域,用来存储元素数据
  • next域:用于指向下一节点

单链表的操作

单链表的所有操作都是从head开始,head本身不存储元素,其next指向第一个节点,然后顺着next链表 进行一步步操作。其尾部节点的next指向为空,这也是判断尾部节点的依据。

插入节点

向单链表中插入一个新节点,可以通过调整两次next指向来完成。

x为新节点,将其next指向A2,再将A1的next指向X即可。

如果是从尾节点插入,直接将尾节点的next指向新节点就可以了。

删除操作

从单链表中删除一节点,通过修改next指向来实现。

将A1的next 指向为A2,这样就能删除 X, X的内存空间会自动被垃圾回收。

代码实现

public class Node {public String data;public Node next;public Node(String data) {this.data = data;}public String getData() {return data;}public void setData(String data) {this.data = data;}public Node getNext() {return next;}public void setNext(Node next) {this.next = next;}@Overridepublic String toString() {return "Node{" +"data='" + data + '\'' +", next=" + next +'}';}
}
 private Node head = new Node(null);//得有head节点,是单链表的开始
//添加节点
public void add(Node node){Node temp = head;//temp存储头节点while (true) {//判断node是否为空if (temp.next == null){temp.next = node;break;}temp = temp.next;}}

singleLinkedList.add(aaa);
singleLinkedList.add(bbb);

    //指定节点插入元素public void addOfOrder(Node node, String name) {Node temp = head;while (true) {if (temp.next == null){temp.next = node;break;}else if (name == temp.getData()) {node.next = temp.next;temp.next = node;break;}temp = temp.next;}}
singleLinkedList.addOfOrder(eee,"bbb");

//查找获取数据
public Node get(String key) {if (head.next == null) {return null;}Node temp = head.next;while (temp != null){if (temp.data == key) {return temp;}temp = temp.next;}return null;
}
//移除数据public void remove(Node node) {Node temp = head.next;while (true) {if (temp.next == null) {break;}if (temp.next.data == node.data) {temp.next = temp.next.next;//断开连接break;}temp = temp.next;}}

//修改叫这个node节点的名字name
public void update(Node node, String name) {Node temp = head.next;//这句话一般都不变,都要用while (true) {if (temp == null) {break;}if (temp.data == name) {temp.data = node.data;break;}temp = temp.next;}}
//测试
public static void main(String[] args) {Node aaa = new Node("aaa");Node bbb = new Node("bbb");Node ccc = new Node("ccc");SingleLinkedList singleLinkedList = new SingleLinkedList();singleLinkedList.add(aaa);singleLinkedList.add(bbb);singleLinkedList.add(ccc);singleLinkedList.print();System.out.println("=====================");Node eee = new Node("eee");singleLinkedList.addOfOrder(eee,"bbb");singleLinkedList.print();System.out.println("=====================");System.out.println(singleLinkedList.get("eee"));System.out.println(singleLinkedList.get("qqq"));System.out.println("=====================");singleLinkedList.remove(ccc);singleLinkedList.print();System.out.println("=====================");singleLinkedList.update(new Node("www"), "eee");singleLinkedList.print();

双向链表

双向链表其节点由三部分构成:

  • prev域:用于指向上一节点

  • data域:数据域,用来存储元素数据

  • next域:用于指向下一节点

双向链表的操作

双向链表的操作可以从两端开始,从第一个节点通过next指向可以一步步操作到尾部,从最后一个节点 通过prev指向可以一步步操作到头部。

插入节点

像双向链表中插入一个节点,需要调整两次 pre指向 和 两次 next 指向。

X为新节点,将A1的next指向X,将x的next指向A2,将A2的pre指向X,将X 的pre指向A1。

删除节点

从双向链表中删除一个节点,需要调整一次 pre 指向 和 一次 next 指向就可以了。

将A1的 next指向 A2, 将A2的pre 指向 A1。

代码实现

public class DoubleNode {public final int key;public String value;public DoubleNode pre;public DoubleNode next;public DoubleNode(int key, String value) {this.key = key;this.value = value;}@Overridepublic String toString() {return "DoubleNode{" +"key=" + key +", value='" + value + '\'' +'}';}
}
public class DoubleLinkedList {public DoubleNode first = null; //双链表的头部,也就是第一个节点public DoubleNode last = null; //双链表的尾部,也就是最后一个节点/*** @Description //TODO 从尾部添加节点*/public DoubleLinkedList addToTail(DoubleNode node) {if (last == null) {first = node;} else {last.next = node;node.pre = last;}last = node;return this;}/*** @Description //TODO 从头部开始添加*/public DoubleLinkedList addToHead(DoubleNode node) {if (first == null) {last = node;} else {node.next = first;first.pre = node;}first = node;return this;}/*** @Description //TODO 按照key key顺序添加*/public DoubleLinkedList addOfOrder(DoubleNode node) {if (first == null) {first = node;last = node;return this;}
//node 比头节点小,将 node 设为头肩if (first.key > node.key) {first.pre = node;node.next = first;first = node;return this;}
//node 比尾节点大,将node变为 尾节点if (node.key > last.key) {last.next = node;node.pre = last;last = node;return this;}DoubleNode temp = first.next;while (true) {if (temp.key > node.key) {node.next = temp;node.pre = temp.pre;temp.pre.next = node;temp.pre = node;break;}temp = temp.next;}return this;}/*** @Description //TODO 获取节点*/public DoubleNode get(int key) {if (first == null) {return null;}DoubleNode temp = first;while (temp != null) {if (temp.key == key) {return temp;}temp = temp.next;}return null;}/*** @Description //TODO 删除*/public DoubleLinkedList remove(DoubleNode node) {if (first == null) {return this;}
//如果删除的是头节点if (first == node) {first.next.pre = null;first = first.next;return this;}
//如果删除的是为节点if (last == node) {last.pre.next = null;last = last.pre;return this;}DoubleNode temp = first.next;while (temp != null) {if (temp.key == node.key) {temp.pre.next = temp.next;temp.next.pre = temp.pre;break;}temp = temp.next;}return this;}/*** @Description //TODO*/public DoubleLinkedList update(DoubleNode node) {if (first == null) {return this;}DoubleNode temp = first;while (temp != null) {if (temp.key == node.key) {temp.value = node.value;break;}temp = temp.next;}return this;}public void print() {if (first == null) {return;}DoubleNode temp = first;while (temp != null) {System.out.println(temp);temp = temp.next;}}public static void main(String[] args) {DoubleNode aaa = new DoubleNode(1, "aaa");DoubleNode bbb = new DoubleNode(2, "bbb");DoubleNode ccc = new DoubleNode(6, "ccc");DoubleLinkedList doubleLinkedList = new DoubleLinkedList();doubleLinkedList.addToTail(aaa);doubleLinkedList.addToTail(bbb);doubleLinkedList.addToTail(ccc);doubleLinkedList.print();System.out.println("===================");DoubleNode ddd = new DoubleNode(4, "ddd");doubleLinkedList.addToHead(ddd);doubleLinkedList.print();System.out.println("===================");DoubleNode eee = new DoubleNode(3, "eee");doubleLinkedList.addOfOrder(eee);doubleLinkedList.print();System.out.println("===================");System.out.println(doubleLinkedList.get(7));System.out.println("===================");doubleLinkedList.remove(new DoubleNode(1, "aaa"));doubleLinkedList.print();System.out.println("===================");doubleLinkedList.update(new DoubleNode(2, "herb"));doubleLinkedList.print();}
}

源码分析

LinkedList特性

  1. LinkedList 集合底层实现的数据结构为双向链表
  2. LinkedList 集合中元素允许为 null
  3. LinkedList 允许存入重复的数据
  4. LinkedList 中元素存放顺序为存入顺序。
  5. LinkedList 是非线程安全的
  6. 如果在频繁的插入,或者删除数据时,就用linkedList性能会更好。

继承结果及层次关系

类的属性

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
//LinkedList 中的节点个数
transient int size = 0;
//LinkedList 链表的头节点
transient Node<E> first;
//LinkedList 链表的 尾节点
transient Node<E> last;
}

构造方法

  1. 空构造器
//空构造器生成一个空链表 ==> frist = last = null
public LinkedList() {
}
  1. 有参构造器
// 将集合 c 中的 各个元素构建成 LinkedList 链表
public LinkedList(Collection<? extends E> c) {
//调用无参构造器
this();
//添加集合中的所有元素
addAll(c);
}

内部类(Node)

private static class Node<E> {E item; //节点的值Node<E> next; //用于指向下一节点(后继)Node<E> prev;//用于指向上一节点(前驱)//构造函数,赋值 前驱后继Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

说明:内部类 Node 就是实际的节点,用于存放实际元素的地方

add()

public boolean add(E e) {
//将元素添加到链表的末尾
linkLast(e);
return true;
}

说明:add函数用于向LinkedList中添加一个元素,并且添加到链表尾部。具体添加到尾部的逻辑是由 linkLast函数完成的。

    void linkLast(E e) {//临时节点 l(L的小写)保存last,也就是 l 指向最后一个节点final Node<E> l = last;//将e(值)封装为节点,并且e.perv指向了最后一个节点final Node<E> newNode = new Node<>(l, e, null);//newNode 成为最后一个节点last = newNode;// 判断之前的链表是否为空,如果为空,那么 newNode 就成为了头节点if (l == null)first = newNode;else //否则将之前的尾节点 的 next 指向 newNode(新节点)l.next = newNode;size++;///添加了节点,size要自增modCount++;}

的末尾
linkLast(e);
return true;
}


说明:add函数用于向LinkedList中添加一个元素,并且添加到链表尾部。具体添加到尾部的逻辑是由 linkLast函数完成的。
void linkLast(E e) {//临时节点 l(L的小写)保存last,也就是 l 指向最后一个节点final Node<E> l = last;//将e(值)封装为节点,并且e.perv指向了最后一个节点final Node<E> newNode = new Node<>(l, e, null);//newNode 成为最后一个节点last = newNode;// 判断之前的链表是否为空,如果为空,那么 newNode 就成为了头节点if (l == null)first = newNode;else //否则将之前的尾节点 的 next 指向 newNode(新节点)l.next = newNode;size++;///添加了节点,size要自增modCount++;
}

Day 09 List子接口LinkedList相关推荐

  1. Collection集合接口及其子接口、实现类

    1. Collection 接口简介 2. Collection的子接口 2.1 List接口 List接口的实现类 ① ArrayList ② Vector ③ Stack ④ LinkedList ...

  2. 【Java8】堆栈/队列/数组/链表/红黑树,List/set子接口,hashcode/hashset,Map/内部接口,/统计字符个数,debug,斗地主,Collections,TreeSet

    文章目录 1.堆栈/队列/数组/链表:数据结构即计算机组织管理数据的方式,堆栈指的是内存图中的栈,不是堆 2.红黑树:二查,二查平,二查平1倍 3.List子接口:集合,IndexOutOfBound ...

  3. JavaSE进阶之(十)Map 子接口之 ConcurrentHashMap

    十.Map 子接口之 ConcurrentHashMap 10.1 JDK 1.7 中的 ConcurrentHashMap 01.JDK 1.7 中 ConcurrentHashMap 底层结构 0 ...

  4. JavaSE入门学习34:Java集合框架之Collection接口、子接口及其实现类

    一Collection接口 Collection接口定义了存取一组对象的方法,其子接口Set.List和Queen分别定义了存储方式. 使用Collection接口需要注意: 1Collection接 ...

  5. Java-Collection的子接口-List集合

    文章目录 List集合 Demo1 List 实现类 ArrayList ArrayList源码分析 Vector LinkedList LinkedList源码分析 ArrayList和Linked ...

  6. 集合之Collection家族的 List接口+LinkedList+Vector+Stack及Set接口+HashSet+LinkedHashSet+TreeSet

    集合之Collection家族的 List接口+LinkedList+Vector+Stack及Set接口+HashSet+LinkedHashSet+TreeSet 一.LinkedList 1.L ...

  7. Spring Boot——[JPA 无法注入 JpaRepository 子接口问题]解决方案

    问题描述 Error starting ApplicationContext. To display the conditions report re-run your application wit ...

  8. 怎么把路由的#号去掉_VLAN应用篇系列:交换机VLAN间路由与传统单臂路由(子接口)方式...

    1 说明 之前已经讲解过了思科交换机的VLAN间路由以及路由器与二层交换机组网的单播路由形式[子接口],这次主要讲解华为上面的VLAN间路由的配置,以及单臂路由的组网方式.华为的三层VLAN接口,就叫 ...

  9. linux系统子接口配置文件,Linux网卡绑定、子接口-IP别名

    查看网卡线缆状态: mii-tool eth0 查看网卡底层信息: ethtool eth0 ethtool -i eth0   查看网卡驱动信息 ethtool -S eth0  查看网卡状态统计信 ...

最新文章

  1. 给热爱学习的同学们推荐一些顶级的c# Blogs链接
  2. Python 是怎么火起来的? 转载 2018年01月12日 00:00:00 133 图:Python 之父 Guido 正在设计 Python 语言,结果家里突然潜入一条大蟒蛇,一番激烈斗争,大
  3. hadoop启动报错:localhost: ssh: Could not resolve hostname localhost
  4. AndroidStudio部署项目时出现错误:Instant Run requires 'Tools | Android | Enable ADB integration' to be enabled
  5. 【LCT】网络(luogu 2173/ZJOI2011)
  6. mysql在哪里写代码_[译] 如何写好 Go 代码
  7. C++学习:第一章 开始
  8. 199.二叉树的右视图
  9. hplus java,HPlus(H+) 后台管理模板带文档V 4.1.1-完整版
  10. 一个简单的java程序
  11. 科技爱好者周刊(第 160 期):中年码农的困境
  12. 用无线路由器同步或备份PassXYZ数据,教你如何把无线路由器打造成网络存储
  13. 禁止所有搜索引擎蜘蛛的爬行收录
  14. 优步和滴滴激战中国市场
  15. Python 快速入门学习
  16. Mac Charles 抓包 iPhone Https(详细流程)
  17. Java数据结构03-------------链表
  18. hdu 1114Piggy-Bank(完全背包)
  19. js 保留两位小数的方法总结
  20. 使用爬虫实现代理IP池之放弃篇

热门文章

  1. 消费新品周报 | TCL发布中国首款可旋转智慧大屏;麦卢卡蜂蜜品牌BEE+登陆中国...
  2. Flink一站式平台 StreamX 1.2.2 正式发布, 迄今最稳定可用版本
  3. 效用最大化准则:离散选择模型的核心(Probit模型上篇)——离散选择模型之七
  4. 高数-不定积分--凑积分(第一类换元法)
  5. [NOIP2000]单词接龙(牛客)
  6. 模块化开发一个电子商务网站
  7. java的Intersect用法_intersect、minus的用法
  8. 黄淮学院计算机重点学科,黄淮学院专业排名 最好的专业有哪些
  9. 利用百度AI平台+pyqt5实现自动识别银行卡小工具
  10. 新型冠状病毒传播规律离散微观模型(结果与实际情况一致)-附源码