Java基础之:List——LinkedList

LinkedList简单介绍

LinkedList实现了双向链表(数据结构)和双端队列特点。

实现了List接口,可以添加任意元素(即可以重复和null),线程不安全。

LinkedList底层实现分析

  1. LinkedList底层维护了一个双向链表

  2. LinkedList中维护了两个属性first和last,分别指向首节点和尾节点

  3. 每个节点(数据结构中将节点都称作Node对象),里面又维护了prev、next、item三个属性。其中prev指向前一个Node,next指向后一个Node,最终实现双向链表。

  4. 所以LinkedList的元素添加与删除不是通过数组完成的,效率较高。

模拟最简单的双向链表:

package class_LinkedList;public class ClassTest01_DoubleLinkedList {        public static void main(String[] args) {                Node first = null;//首先定义一个first节点,作为标记位置存在                //当添加一个节点时,让first节点指向此节点        Node node1 = new Node(first, null, "小范");        first = node1;                //添加第二个节点,在构造时,让第二个节点的prev属性指向前一个节点node1        Node node2 = new Node(node1, null, "小黄");        node1.next = node2;  //让node1的next指向node2,实现双向连接                //添加第三个节点        Node node3 = new Node(node2, null, "小雨");        node2.next = node3;                //结尾 ,使用last节点,让last节点指向node3,因为node3的next为null代表链表结束        Node last = node3;                //链表遍历,通常都使用一个临时temp节点来用于遍历链表,不要使用first!        Node temp = first;                //链表从前向后遍历        System.out.println("==========从前向后============");        while(true) {            System.out.println(temp);            if(temp.next == null) { //last节点的next属性为null                break;            }            temp = temp.next; //将temp向后移        }                //链表从后向前遍历        System.out.println("==========从后向前============");        temp = last;        while(true) {            System.out.println(temp);            if(temp.prev == null) { //first节点的prev属性为null                break;            }            temp = temp.prev; //将temp向前移        }                //添加节点,让需要添加位置的前后节点分别指向要添加的节点即可。        //创建需要添加的节点,让其prev属性指向要添加位置的前一个节点,next属性指向要添加位置的后一个节点        Node add = new Node(node1,node2,"add"); //在第一个和第二个节点中间插入一个节点        //将node1的next指向add,node2的prev指向add,完成连接,此时node1与node2之间的连接自然就断开了        node1.next = add;        node2.prev = add;                //再次遍历检查是否添加成功        System.out.println("==========添加后===========");        temp = first;        while(true) {            System.out.println(temp);            if(temp.next == null) { //last节点的next属性为null                break;            }            temp = temp.next; //将temp向后移        }    }}class Node{    //说明  这里为了方便演示案例,没有进行封装,实际开发中需要封装        Node prev;  //指向前一个节点    Node next;  //指向后一个节点    String name; //每个节点的自有属性    public Node(Node prev, Node next, String name) {        this.prev = prev;        this.next = next;        this.name = name;    }        @Override    public String toString() {        return "Node [name=" + name + "]";    }}

程序输出:

==========从前向后============

Node [name=小范]

Node [name=小黄]

Node [name=小雨]

==========从后向前============

Node [name=小雨]

Node [name=小黄]

Node [name=小范]

==========添加后===========

Node [name=小范]

Node [name=add]

Node [name=小黄]

Node [name=小雨]

LinkedList常用方法

package class_LinkedList;import java.util.LinkedList;public class ClassTest02_LinkedListMethods {    @SuppressWarnings({ "rawtypes", "unchecked" })    public static void main(String[] args) {        LinkedList linkedList = new LinkedList();        // 添加        for (int i = 0; i < 2; i++) {            linkedList.add("AAA" + i);        }        String kk = "yyy";        linkedList.add(kk);        linkedList.add(2, kk);        // 遍历        for (Object object : linkedList) {            System.out.println(object);        }        // 删除        // linkedList.remove(0);        // linkedList.remove(kk);                System.out.println("=================");        //替换        linkedList.set(0, "川农");        for (Object object : linkedList) {            System.out.println(object);        }                System.out.println("=================");                //查找,也可以使用下标进行访问        Object object = linkedList.get(0);        System.out.println("object=" + object);                //LinkedList特有方法,获取首尾节点        System.out.println(linkedList.getFirst());        System.out.println(linkedList.getLast());    }}

添加节点源码分析

默认添加:

带下标位置的添加:

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内部类维护了next与prev属性。

LinkedList与ArrayList对比

如何选择ArrayList和LinkedList:

  1. 如果我们改查的操作多,选择ArrayList

  2. 如果我们增删的操作多,选择LinkedList

  3. 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList

  4. 在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.

(0)

相关推荐