LinkedList 基本使用

简介: LinkedList 基本使用

1. LinkedList 简介

1) LinkedList 底层实现了 双向链表和双端队列 特点
2) 可以添加任意元素(元素可以重复),包括null
3) 线程不安全,没有实现同步

2. LinkedList 底层操作机制

在这里插入图片描述

1) LinkedList 底层维护了一个双向链表.
2) LinkedList 中维护了两个属性firstlast分别指向首节点和尾节点
3) 每个节点(Node对象) ,里面又维护了 prev、 next. item 三个属性,其中 prev 指向前一个,通过 next 指向后一个节点。 最终实现双向链表
4) 所以 LinkedList 的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
5) 模拟一个简单的双向链表,如:
在这里插入图片描述

  • 双向链表的简单使用
public class LinkedList01 {

    public static void main(String[] args) {

        // 模拟一个简单的双向链表

        Node tom = new Node("tom");
        Node jack = new Node("jack");
        Node xdr = new Node("xdr");

        //连接三个点,形成双向链表
        // tom->jack->xdr
        tom.next = jack;
        jack.next = xdr;
        // xdr->jack->tom
        xdr.pre = jack;
        jack.pre = tom;

        Node first = tom;//让 first 引用指向 jack,就是双向链表的头节点
        Node last = xdr; //让 last 引用指向 xdr,就是双向链表的尾节点

        // 从头到尾进行遍历
        System.out.println("===从头到尾进行遍历===");
        while (true) {
            if (first == null) {
                break;
            }
            //输出 first 信息
            System.out.println(first);
            first = first.next;
        }

        //从尾到头的遍历
        System.out.println("====从尾到头进行遍历====");
        while (true) {
            if (last == null) {
                break;
            }
            //输出 last 信息
            System.out.println(last);
            last = last.pre;
        }

    }
}

// 定义一个 Node 类,Node 对象,表示双向链表的一个节点
class Node {
    public Object item; // 真正存放的数据
    public Node next; // 指向后一个节点
    public Node pre; // 指向前一个节点

    public Node(Object name) {
        this.item = name;
    }

    public String toString() {
        return "Node name=" + item;
    }
}

在这里插入图片描述

  • 在链表中插入元素,如:在 jack 和 xdr 中间插入一个对象 mike
    //先创建一个 Node 结点,name 就是 mike
    Node mike = new Node("mike");
    //下面就把 mike 加入到双向链表了
    mike.next = xdr;
    mike.pre = jack;
    xdr.pre = mike;
    jack.next = mike;
    
    //让 first 再次指向 tom
    first = tom;//让 first 引用指向 tom,就是双向链表的头结
    System.out.println("===从头到尾进行遍历===");
    while (true) {
        if (first == null) {
            break;
        }
        //输出 first 信息
        System.out.println(first);
        first = first.next;
    }
    
    // 从尾到头进行遍历
    last = xdr; //让 last 重新指向最后一个节点
    //从尾到头的遍历
    System.out.println("====从尾到头进行遍历====");
    while (true) {
        if (last == null) {
            break;
        }
        //输出 last 信息
        System.out.println(last);
        last = last.pre;
    }

在这里插入图片描述

3. LinkedList 源码分析

1、案例:打断点进行源码分析

    LinkedList linkedList = new LinkedList();
    linkedList.add(1);
    linkedList.add(2);
1. LinkedList linkedList = new LinkedList();
   public LinkedList() {}
   
2. 这时 linkeList 的属性 first = null  last = null

3. 执行 添加
    public boolean add(E e) {
         linkLast(e);
         return true;
     }  
     
4.将新的结点,加入到双向链表的最后
  void linkLast(E e) {
     final Node<E> l = last;
     final Node<E> newNode = new Node<>(l, e, null);
     last = newNode;
     if (l == null)
         first = newNode;
     else
         l.next = newNode;
     size++;
     modCount++;
 }

2、演示删除节点的源码:linkedList.remove(); 这里默认删除的是第一个节点

1. 执行 removeFirst
   public E remove() {
       return removeFirst();
   }
   
2. 执行
   public E removeFirst() {
       final Node<E> f = first;
       if (f == null)
           throw new NoSuchElementException();
       return unlinkFirst(f);
   }
   
3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
   private E unlinkFirst(Node<E> f) {
       // assert f == first && f != null;
       final E element = f.item;
       final Node<E> next = f.next;
       f.item = null;
       f.next = null; // help GC
       first = next;
       if (next == null)
           last = null;
       else
           next.prev = null;
       size--;
       modCount++;
       return element;
   }

4. LinkedList 增删改查案例

  • 删除一个节点
LinkedList linkedList = new LinkedList();
   linkedList.add(1);
   linkedList.add(2);

   System.out.println(linkedList);
   linkedList.remove();
   System.out.println(linkedList);

在这里插入图片描述

  • 修改某个节点对象,index 索引是按照 0 开始编号的
LinkedList linkedList = new LinkedList();
    linkedList.add(1);
    linkedList.add(2);
    linkedList.add(3);
    
    System.out.println(linkedList);
    linkedList.remove();
    System.out.println(linkedList);
    
    linkedList.set(1, 2233);
    
    System.out.println(linkedList);

在这里插入图片描述

  • 得到某个结点对象,get(1) 是得到双向链表的第二个对象
Object o = linkedList.get(1);
System.out.println(o);

在这里插入图片描述

  • LinkedList 是 实现了List接口,遍历方式可以用 迭代器、增强for、普通for 进行遍历
    System.out.println("===迭代器遍历===");
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()) {
        Object next = iterator.next();
        System.out.println("next=" + next);
    }
    
    System.out.println("===增强for循环遍历===");
    for (Object o : linkedList) {
        System.out.println("o=" + o);
    }
    
    System.out.println("===普通for循环遍历===");
    for (int i = 0; i < linkedList.size(); i++) {
        System.out.println(linkedList.get(i));
    }

在这里插入图片描述

5. ArrayList和LinkedList比较

在这里插入图片描述

  • 如何选择 ArrayList 和 LinkedList :
  1. 如果改查的操作多,选择ArrayList
  2. 如果增删的操作多,选择LinkedList
  3. 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
  4. 在一个项目中,根据业务灵活选择,一个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务需求来进行选择。
目录
相关文章
|
6月前
|
存储 缓存 Java
LinkedList 源码解读
LinkedList 源码解读
36 1
|
存储 Java 索引
每日一道面试题之ArrayList 和 LinkedList 的区别是什么?
每日一道面试题之ArrayList 和 LinkedList 的区别是什么?
|
6月前
|
调度 uml 索引
|
存储 Java 开发者
Java-数据结构(三)-List:ArrayList和LinkedList及其相关面试题
Java-数据结构(三)-List:ArrayList和LinkedList及其相关面试题
219 0
|
6月前
|
Java
java数据结构,如何使用ArrayList和LinkedList?
java数据结构,如何使用ArrayList和LinkedList?
46 1
|
6月前
|
存储
Arrylist 与 Linkedlist 的区别
Arrylist 与 Linkedlist 的区别
59 1
|
6月前
面试题之:ArrayList和LinkedList有哪些区别
面试题之:ArrayList和LinkedList有哪些区别
ArrayList与LinkedList获取指定元素对比(源码分析)
ArrayList与LinkedList获取指定元素对比(源码分析)
76 0
ArrayList与LinkedList移除指定元素对比(源码分析)
ArrayList与LinkedList移除指定元素对比(源码分析)
48 0
|
存储 Java
Java集合学习:LinkedList源码详解
Java集合学习:LinkedList源码详解
146 0