百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Java路径-34-Java的LinkedList(未检测到java sdk环境请在配置中添加sdk安装路径)

toyiye 2024-08-10 21:44 14 浏览 0 评论

1 LinkedList的概念

LinkedList本质上是一个双向链表。

那么什么是链表呢?链表原先是C/C++的概念,是一种线性的存储结构,意思是将要存储的数据存在一个存储单元里面,这个存储单元里面除了存放有待存储的数据以外,还存储有其下一个存储单元的地址(下一个存储单元的地址是必要的,有些存储结构还存放有其前一个存储单元的地址),每次查找数据的时候,通过某个存储单元中的下一个存储单元的地址寻找其后面的那个存储单元。

而LinkedList是双向链表,在list中的每个元素,在存储自身元素外,还额外存储了其前一个和后一个元素的地址,所以 也就可以很方便地根据当前元素获取到其前后的元素。链表的尾部元素的后一个节点是链表的头节点;而链表的头结点前一个节点则是则是链表的尾节点。

由于LinkedList的底层是双向链表,因此其顺序访问的效率非常高,而随机访问的效率就比较低了,因为通过索引去访问的时候,首先会比较索引值和链表长度的1/2,若前者大,则从链表尾开始寻找,否则从链表头开始寻找,这样就把双向链表与索引值联系起来了。



2 LinkedList的定义

根据LinkedList的声明代码,可以看到它除了实现List接口外,还实现了Deque接口,而Deque主要是一个双端队列,因此LinkedList除了可以作为List使用外,还可以当做队列使用。 ?

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

3 LinkedList的使用

(1)LinkedList的构造

// 1.无参构造       
LinkedList()
//2.使用其他集合容器中的元素构造List      
public LinkedList(Collection<? extends E> c)

代码如下:

public static void main(String[] args) {
    // 构造一个空的LinkedList
    List<Integer> list1 = new LinkedList<>();
    List<String> list2 = new java.util.ArrayList<>();
    list2.add("JavaSE");
    list2.add("JavaWeb");
    list2.add("JavaEE");
    // 使用ArrayList构造LinkedList
    List<String> list3 = new LinkedList<>(list2);
}

(2)LinkedList的其他常用方法介绍

boolean add(E e)    //尾插e

void add(int index,E element)   //将e插入到index位置

boolean addAll(Collection<? extends E> c)   //尾插c中的元素

E remove(int index) //删除Index位置的元素

boolean remove(Object o)    //删除遇到的第一个o

E get(int index)    //获取下标index位置的元素

E set(int index,E element)  //将下标为index位置的元素设置为element

void clear()    //清空

boolean contains(Object o)  //判断o是否在线性表中

int indexOf(Object o)   //返回第一个o所在下标

int lastIndexOf(Object o)   //返回最后一个o所在下标

List<E>subList(int fromIndex,int toIndex)   //截取部分list

代码如下:

public static void main(String[] args) {
    LinkedList<Integer> list = new LinkedList<>();
    list.add(1); // add(elem): 表示尾插
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    list.add(6);
    list.add(7);
    System.out.println(list.size());
    System.out.println(list);
    // 在起始位置插入0
    list.add(0, 0); // add(index, elem): 在index位置插入元素elem
    System.out.println(list);
    list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
    list.removeFirst(); // removeFirst(): 删除第一个元素
    list.removeLast(); // removeLast(): 删除最后元素
    list.remove(1); // remove(index): 删除index位置的元素
    System.out.println(list);
    // contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
    if(!list.contains(1)){
        list.add(0, 1);
    }
    list.add(1);
    System.out.println(list);
    System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置
    System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置
    int elem = list.get(0); // get(index): 获取指定位置元素
    list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
    System.out.println(list);
    // subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
    List<Integer> copy = list.subList(0, 3); 
    System.out.println(list);
    System.out.println(copy);
    list.clear(); // 将list中元素清空
    System.out.println(list.size());
}

(3) LinkedList的遍历

public static void main(String[] args) {
    LinkedList<Integer> list = new LinkedList<>();
    list.add(1); // add(elem): 表示尾插
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    list.add(6);
    list.add(7);
    System.out.println(list.size());
    // foreach遍历
    for (int e:list) {
        System.out.print(e + " ");
    }
    System.out.println();
    // 使用迭代器遍历---正向遍历
    ListIterator<Integer> it = list.listIterator();
    while(it.hasNext()){
        System.out.print(it.next()+ " ");
    }
    System.out.println();
    // 使用反向迭代器---反向遍历
    ListIterator<Integer> rit = list.listIterator(list.size());
    while (rit.hasPrevious()){
        System.out.print(rit.previous() +" ");
    }
    System.out.println();
}

(4)LinkedList的模拟实现

代码如下:

public class MyLinkedList {
    static class LinkedList {
        public int val;
        public LinkedList prev;
        public LinkedList next;
        public LinkedList(int val) {
            this.val = val;
        }

    }
        public LinkedList head;
        public LinkedList last;
    // 2、无头双向链表实现
        //头插法
        public void addFirst(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head = node;
                last = node;
            } else {
                head.prev = node;
                node.next = head;
                head = node;
            }
        }
        //尾插法
        public void addLast(int data){
            LinkedList node = new LinkedList(data);
            if(head==null) {
                head=node;
                last=node;
            } else {
                last.next=node;
                node.prev=last;
                last = node;
            }

        }
        //任意位置插入,第一个数据节点为0号下标
        public void addIndex(int index,int data){
            if(index<0 || index>size()) {
                System.out.println("位置不合法");
            }
            if(index==0) {
                addLast(data);
                return;
            }
            if(index==size()) {
                addLast(data);
                return;
            }

            LinkedList node = new LinkedList(data);
            LinkedList cur = findIndex(index);
            node.next = cur;
            cur.prev.next = node;
            node.prev = cur.prev;
            cur.prev=node;
        }

        public LinkedList findIndex(int index) {
            LinkedList cur = head;
            while (index!=0) {
                cur = cur.next;
                index--;
            }
            return cur;
        }
        //查找是否包含关键字key是否在链表当中
        public boolean contains(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    return true;
                }
                cur = cur.next;
            }
            return false;
        }
        //删除第一次出现关键字为key的节点
        public void remove(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    //头节点
                    if(cur==head) {
                        head = head.next;
                        if (head!=null) {
                            head.prev = null;
                        }
                    } else {
                        //中间 节点和 尾部节点
                        cur.prev.next = cur.next;
                        if(cur.next!=null) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                    return;
                }
                cur=cur.next;
            }
        }
        //删除所有值为key的节点
        public void removeAllKey(int key){
            LinkedList cur = head;
            while (cur!=null) {
                if(cur.val==key) {
                    //头节点
                    if(cur==head) {
                        head = head.next;
                        if (head!=null) {
                            head.prev = null;
                        }
                    } else {
                        //中间 节点和 尾部节点
                        cur.prev.next = cur.next;
                        if(cur.next!=null) {
                            //中间
                            cur.next.prev = cur.prev;
                        }else {
                            //尾部
                            last = last.prev;
                        }
                    }
                }
                cur=cur.next;
            }
        }
        //得到的长度
        public int size(){
            int len = 0;
            LinkedList cur = head;
            while (cur!=null) {
                len++;
                cur=cur.next;
            }
            return len;
        }
        public void display(){
            LinkedList cur = head;
            while (cur!=null) {
                System.out.print(cur.val+" ");
                cur=cur.next;
            }
            System.out.println();
        }
        public void clear(){
            LinkedList cur = head;
            while (cur!=null) {
                LinkedList curNext = cur.next;
                cur.prev = null;
                cur.next = null;
                cur = curNext;
            }
            head=null;;
            last=null;
        }

}

3 常用的方法

方法

说明

public boolean add(E e)

链表末尾添加元素,返回是否成功,成功为 true,失败为 false。

public void add(int index, E element)

向指定位置插入元素。

public boolean addAll(Collection c)

将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。

public boolean addAll(int index, Collection c)

将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。

public void addFirst(E e)

元素添加到头部。

public void addLast(E e)

元素添加到尾部。

public boolean offer(E e)

向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。

public boolean offerFirst(E e)

头部插入元素,返回是否成功,成功为 true,失败为 false。

public boolean offerLast(E e)

尾部插入元素,返回是否成功,成功为 true,失败为 false。

public void clear()

清空链表。

public E removeFirst()

删除并返回第一个元素。

public E removeLast()

删除并返回最后一个元素。

public boolean remove(Object o)

删除某一元素,返回是否成功,成功为 true,失败为 false。

public E remove(int index)

删除指定位置的元素。

public E poll()

删除并返回第一个元素。

public E remove()

删除并返回第一个元素。

public boolean contains(Object o)

判断是否含有某一元素。

public E get(int index)

返回指定位置的元素。

public E getFirst()

返回第一个元素。

public E getLast()

返回最后一个元素。

public int indexOf(Object o)

查找指定元素从前往后第一次出现的索引。

public int lastIndexOf(Object o)

查找指定元素最后一次出现的索引。

public E peek()

返回第一个元素。

public E element()

返回第一个元素。

public E peekFirst()

返回头部元素。

public E peekLast()

返回尾部元素。

public E set(int index, E element)

设置指定位置的元素。

public Object clone()

克隆该列表。

public Iterator descendingIterator()

返回倒序迭代器。

public int size()

返回链表元素个数。

public ListIterator listIterator(int index)

返回从指定位置开始到末尾的迭代器。

public Object[] toArray()

返回一个由链表元素组成的数组。

public T[] toArray(T[] a)

返回一个由链表元素转换类型而成的数组。

4 ArrayList和LinkedList的区别

  • 在存储空间上,ArrayList在物理上一定连续,LinkedList在逻辑上连续,但物理上不一定连续
  • ArrayList支持随机访问,时间复杂度为O(1),但是LinkedList不支持,时间复杂度为O(N)
  • ArrayList在头插时需要搬移元素,效率低O(N),LinkedList只需要修改引用的指向,时间复杂度为O(1)
  • ArrayList在插入时空间不够时需要扩容,但是LinkedList没有容量的概念
  • ArrayList应用于“元素高效存储和频繁访问”,LinkedList应用于“任意位置插入和删除频繁”

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码