8-LinkedList

LinkedList实现类

常用方法及使用

        /*
        LinkedList常用方法
        增加: addFirst(E e)  addLast(E e)
             offer(E e)  offerFirst(E e)  offerLast(E e)
        删除: poll()
             pollFirst() pollLast()
             removeFirst() removeLast()
        修改:
        查看: element()
             getFirst()  getLast()
             indexOf(Object o)  lastIndexOf(Object o)
             peek()
             peekFirst()  peekLast()
        判断:
         */

        //创建一个LinkedList集合对象
        LinkedList<String> list = new LinkedList<>();//LinkedList是一个泛型类,在创建实例时推荐把泛型加上
        list.add("aaaaa");//填数据
        list.add("bbbbb");
        list.add("ccccc");
        list.add("ddddd");
        list.add("eeeee");
        list.add("bbbbb");
        list.add("fffff");
        //LinkedList可以添加重复数据

        //向头添加一个元素addFirst
        list.addFirst("jj");
        //向尾添加一个元素addLast
        list.addLast("hh");

        //offer也是添加元素
        list.offer("kk");//添加元素在尾端
        list.offerFirst("pp");//头部
        list.offerLast("rr");//尾
        System.out.println(list);

        //删除
        System.out.println(list.poll());//删除头上元素并且将删除的元素输出
        System.out.println(list.pollFirst());//同上
        System.out.println(list.removeFirst());//同上
        System.out.println(list.pollLast());//删除尾元素并将删除的元素输出
        System.out.println(list.removeLast());//同上
        System.out.println(list);
        /*
        疑问:功能都一样,为啥有两个?
        做以下操作
        list.clear();//清空集合
        System.out.println(list);
        System.out.println(list.pollFirst());//输出null--->JDK1.6开始,新版本的,提高的代码的健壮性
        list.removeFirst();//报错--->抛出异常,早期的方法
         */

        //集合的遍历
        System.out.println("----------------");
        //1.普通for
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("----------------");
        //2.增强for
        for (String s :
                list) {
            System.out.println(s);
        }
        System.out.println("----------------");
        //3.迭代器
        /*  Iterator<String> it = list.iterator();//自动加的泛型String,因为泛型确定
        while (it.hasNext()){
            System.out.println(it.next());
        }*/  //下面的方式更好,节省了内存,it作用完就释放
        for (Iterator<String> it = list.iterator(); it.hasNext();){
            System.out.println(it.next());//it.next()方法直接进行下一步迭代,故上面for循环不写迭代语句
        }

底层

对比

ArrayList

ArrayList:数据结构

  • 物理结构:紧密结构(在内存里紧挨着一个一个的)
  • 逻辑结构:线性表(数组)

LinkedList

LinkedList:数据结构

  • 物理结构:跳转结构
  • 逻辑结构:线性表(链表)
    • LinkedList的链表是双向的

LinkedList底层链表

  • 链表:双向链表

例:放入三个元素:“aa”,“bb”,“cc”

  1. 将放入的元素“aa”封装成对象
    • 前一个元素地址null |当前存入元素 "aa" |后一个元素地址null
    • 以上整个这个对象才是链表中的一个节点
  2. 后面元素依次放

模拟LinkedList链表

  • 节点类Node
public class Node {//节点类
    //三个属性:
    //上一个元素的地址:
    private Node pre;//上一个元素实际是一个节点
    //当前存入的元素:
    private Object obj;//可能是各式各样的类型,故是Object类型
    //下一个元素地址
    private Node next;

    //属性私有化--->提供set、get方法
    public Node getPre() {
        return pre;
    }

    public void setPre(Node pre) {
        this.pre = pre;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    //提供一个toString,展示元素到底有什么数据
    @Override
    public String toString() {
        return "Node{" +
                "pre=" + pre +
                ", obj=" + obj +
                ", next=" + next +
                '}';
    }
}
  • 实现LinkedList集合
public class MyLinkedList {//创建自己的LinkedList集合,不跟系统的名一样
    //链中一定有一个首节点
    Node first;
    //链中一定有一个尾节点
    Node last;
    //计数器
    int count = 0;
    //提供一个构造器
    public MyLinkedList() {
    }
    //添加元素的方法:
    public void add(Object o){
        if(first == null){//证明你添加的元素是第一个节点
            //将添加的元素封装为一个Node对象:
            Node n = new Node();
            n.setPre(null);
            n.setObj(o);
            n.setNext(null);
            //当前链中第一个节点变为n
            first = n;
            //当前链中最后一个节点变为n
            last = n;
        }else {//证明已经不是链中第一个节点了
            //将添加的元素封装为一个Node对象:
            Node n = new Node();
            n.setPre(last);//n的上一个节点一定是当前链中的最后一个节点last
            n.setObj(o);
            n.setNext(null);
            //当前链中的最后一个节点的下一个元素要指向n
            last.setNext(n);
            //将最后一个节点变成n
            last = n;
        }
        //链中元素数量加1
        count++;
    }

    //得到集合中元素的数量
    public int getSize(){
        return count;
    }

    //通过下标得到元素;
    public Object get(int index){
        /*
        链表没有直接的下标--->
        通过从头元素计数开始往下数--->
        得到对应位置元素
         */
        //获取链表的头元素
        Node n = first;
        //循环到对应元素跳出
        for (int i = 0; i < index; i++) {
            n = n.getNext();
        }
        return n.getObj();
    }
}

class Test{
    public static void main(String[] args) {
        //创建一个MyLinkedList集合对象
        MyLinkedList m1 = new MyLinkedList();
        m1.add("aa");
        m1.add("bb");
        m1.add("cc");
        System.out.println(m1.getSize());
        System.out.println(m1.get(2));
    }
}

LinkedList的API

public class LinkedList<E>{//E是一个泛型,具体的类型要在实例化的时候才会最终确定
    transient int size = 0;//集合中元素数量
    //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;
        }
    }
    transient Node<E> first;//首节点
    transient Node<E> last;//尾节点
    //空构造器
    public LinkedList() {
    }
    //添加元素操作
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    void linkLast(E e) {//添加的元素e
        final Node<E> l = last;//将链表中的last节点给l 如果是第一个元素的化 l为null
        //将元素封装为一个Node具体的对象
        final Node<E> newNode = new Node<>(l, e, null);
        //将链表的last节点指向新的创建的对象:
        last = newNode;
        if (l == null)//如果添加的是第一个节点
            first = newNode;//将链表的first节点指向为新节点
        else//如果不是第一个节点
            l.next = newNode;//将l的下一个指向为新的节点
        size++;//集合中元素数量加1操作
        modCount++;
    }
    ///获取集合中元素数量
    public int size() {
        return size;
    }
    //通过索引得到元素
    public E get(int index) {
        checkElementIndex(index);//健壮性考虑
        return node(index).item;
    }
    
    Node<E> node(int index) {
        // size>>1 位运算-->提高效率,二分--->提高效率
        //如果index在链表的前半段,那么从前往后找
        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {//如果index在链表的后半段,那么从后往前找
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
}
posted @ 2024-08-22 18:11  呆头尖瓜  阅读(1)  评论(0编辑  收藏  举报