Java中的集合类:LinkedList

Java中的集合类

1、LinkedList

1.1、LinkedList的简介

  LinkedList集合是和ArrayList集合一样,也是一个实现单值存储的集合类,因此实现了所有单值存储集合类都会实现的父接口:Collection接口,此外该类还继承了AbstractSequentialList类和实现了这些接口:Serializable 接口, Cloneable接口 , Iterable接口 , Deque接口 , List接口, Queue接口。使用该类时需要进行导包操作,导入的包名为:java.util.LinkedList。

  LinkedList集合的特点是:该集合在进行数据的删除和插入操作时效率高,而相对的使用该集合进行数据的遍历和查询操作的效率较低,这和ArrayList集合的特点是刚好相反的,而且在多线程的程序中使用该集合进行数据的处理,会导致线程的安全性比较低。正因为LinkedL集合的这些不足之处,导致该集合在项目上的应用就没有ArrayList集合那么实用和受欢迎,当然也不是完全不用LinkedList集合,只是用的少,所以对于该集合,大家理解它的底层实现原理和相关的功能如何实现就可以了。

  想了解ArrayList集合的相关内容的小伙伴,可以在阅读完这篇文章去看看我关于ArrayList集合的相关博客,文章末尾我会放上博文链接。接下来我介绍关于LinkedList集合的底层实现原理。

1.2、LinkedList的底层实现原理

  LinkedList集合的底层实现结构是一个双向链表。简单的了解链表结构特点就是:列表中的元素除了有你存储的数据之外,还存在指向下一个元素或上一个元素的指针,每个元素都在独立的空间内,互不影响,相互之间通过指针的指向来相互关联。

  而双向链表是链表结构的一种:特点就是列表中的每一个元素都有自己的头指针和尾指针,两个指针分别指向不同的元素,通过指针指向的地址就可以获得该元素的上一个元素或下一个元素,因此只要改变指针的指向就可以做到数据的插入和删除操作,所以LinkedList集合对于数据的插入和删除的效率很高,不像ArrayList集合那样在插入或删除元素后需要移动元素。还有在链表存储数据时分配个每个元素的地址是无序的、散乱的,所以LinkedList集合在执行查询和遍历的操作时的效率会会很低。

  该集合实现的是多线程的异步操作,在多线程的程序中执行异步操作的结果就会导致线程的不安全性。线程不安全主要体现在:多个线程在对集合中的数据进行改动时,会相互影响,从而导致数据的错乱,无法获取准确的数据进行相关的功能操作。

  关于Java中与多线程相关知识的博文链接我已放在文章末尾,感兴趣的小伙伴可以自行了解。介绍完LinkedList集合的底层实现原理,下面就来了解该集合中的一些方法和这些可以实现的功能有哪些。

1.3、LinkedList的相关操作方法

1.3.1、LinkedList的构造方法

  LinkedList集合有两种构造方法:

  1. LinkedList()
  2. LinkedList​(Collection<? extends E> c)

  第一种是无参构造方法,作用是:创建一个空的LinkedList集合;第二种是需要传入参数的构造方法,传入的参数是一个实现了Collection接口的集合,作用是:将你传入的集合转换成LinkedList集合。

  具体的Java代码为:

	//无参构造方法——尖括号内的类型随意选取但必须是包装类
	LinkedList<Integer> list = new LinkedList<>()
	//有参构造方法——将ArrayList集合转换成LinkedList集合
	LinkedList<String> list1 = new LinkedList<>(new ArrayList<String>());

  知道了如何使用LinkedList集合的构造方法创建LinkedList集合之后,我来介绍LinkedList集合中的相关操作的方法。

1.3.2、添加元素的方法

  这类方法方法的作用是:往LinkedList集合中添加你指定的元素。该方法有两种传参方式:

  1. void add​(int index, E element )
  2. boolean add​(E e)

  第一种方法使用后无返回值,使用时需传入两个参数:第一种参数是int类型,代表:你指定的位置,第二个参数是泛型的元素,代表:你要添加到集合中的元素,泛型类型与你的集合中定义的元素类型一样,方法的作用是:从你指定的位置往集合中添加你指定的元素。

  注意:当 (index < 0 || index > size() )满足该条件后会抛出IndexOutOfBoundsException该类异常。

  第二种方法使用后会有一个boolean类型的返回值,使用时需要传入一个泛型类型的参数,代表:你要添加的元素,泛型的类型与你定义集合时的类型一致,方法作用是:往列表的尾部添加你指定的元素,添加成功返回true。

  具体的Java代码为:

public class Test {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(2,4);
        int a = 1;
        for (int i:list ) {
            System.out.println("第"+a+"个元素为:"+i);
            a++;
        }
    }
}

  具体的效果图:

在这里插入图片描述

  可以从效果图看到使用第一种方式添加的元素4在使用了第二种方式添加的元素3之前,因为我指定的位置是下标为2的位置(下标从0开始),所以在第三个位置插入了元素4。

  add方法还有其他衍生出来的方法,我来给大家介绍一下吧。

  add方法的衍生方法有四种:

  1. boolean addAll​(int index, Collection<? extends E> c)
  2. boolean addAll​(Collection<? extends E> c)
  3. void addFirst​(E e)
  4. void addLast​(E e)

  第一、二种方法都是将其他实现的Collection接口的集合中的元素添加到LinkedList集合中,第一种方法是指定位置添加,第二种方法是从列表尾部添加,和add方法是一个道理,第一种方法也是要注意:当( index < 0 || index > size() )满足该条件后会抛出IndexOutOfBoundsException该类异常。

  第三种方法是从列表的开头添加你指定的元素,第四种是从列表的尾部添加你指定的元素。

  这些方法使用的不多,所以就不展示具体代码了,就展示一下用法吧,一下是Java代码:

	//创建LinkedList集合
	LinkedList<Integer> list = new LinkedList<>();
	//往集合的头部添加元素0
	list.addFirst(0);
	//往集合的尾部添加元素5
    list.addLast(5);
    //创建Arraylist集合
    ArrayList<Integer> list1 = new ArrayList<>();
    //往ArrayList集合中添加元素6和8
    list1.add(6);
    list1.add(8);
    //将ArrayList集合中的元素添加到LinkedL集合中
    list.addAll(list1);

  下面是我接着add方法的代码继续编写的Java代码运行效果图:

在这里插入图片描述

  由效果图可以看到元素0插入列表的开头,元素5接着元素3的后面添加,而Arra集合中元素6和8也接着元素5添加到了列表的尾部。

  添加元素的方法除了上述的add方法和其衍生的方法以外,还有一类方法,使用这类方法添加元素后,LinkedList集合相当于变成了一个堆栈。下面就来介绍这类方法吧。

1.3.3、压栈与弹栈操作的方法

  介绍方法前,先来介绍堆栈结构的原理:堆栈中,元素的存储操作叫压栈,元素的删除操作叫弹栈,元素在进行压栈操作后会存放在堆栈的底部,而元素进行弹栈操作时删除的是堆栈顶部的元素,这就导致了元素出现先进后出的现象,就和堆积木一样,只有将上面的积木拿走,下面的积木才可以拿走是一个道理。

  压栈方法和弹栈方法如下:

  1. void push​(E e)
  2. E pop()

  第一种方法是压栈方法,使用该方法后无返回值,使用时需要传入一个泛型元素,代表:你想要进行压栈操作的元素。

  第二种方法是弹栈方法,使用该方法后会有一个泛型的返回值,泛型类型取决集合中的元素是什么类型,该返回值代表:进行弹栈操作后删除的元素。

  具体的Java代码:

public class Test1 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.push(1);
        list.push(2);
        list.push(3);
        list.push(4);
        int a = 1;
        for (int i:list  ) {
            System.out.println("第"+a+"个元素为:"+i);
            a++;
        }
        System.out.println("弹栈操作删除的元素:"+list.pop());
    }
}

  以下是效果图:

在这里插入图片描述

  由效果图可以很清楚的看出,第一个进行压栈的元素1在列表的尾部,最后一个进行压栈操作的元素4在列表的头部,而进行弹栈操作的元素是在列表头部的元素4,这就是典型的堆栈结构会产生的效果。

 介绍完这类特殊的方法,下面来介绍如何获取集合中元素的方法

1.3.4、获取元素的方法

  这类方法的作用是:获取LinkedList集合中你指定的元素,这类方法有以下几种:

  1. E get​(int index)
  2. E getFirst()
  3. E getLast()

  第一种方法使用后会有一个泛型返回值,泛型的类型与集合中的元素一致,使用时传入一个int类型的参数,代表你指定的位置,方法的作用是:获取并返回你指定位置的元素,需要注意:当( index < 0 || index > size() )满足该条件后会抛出IndexOutOfBoundsException该类异常。

  第二种方法使用后会有一个泛型类型的返回值,方法的作用是:获取并返回列表头部的元素。

  第三种方法使用后会有一个泛型类型的返回值,方法的作用是:获取并返回列表尾部的元素。

  具体的Java代码:

public class Test3 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        for (int i=0;i<list.size();i++){
            System.out.println("第"+(i+1)+"个元素为:"+list.get(i));
        }
        System.out.println("列表头部的元素为:"+list.getFirst());
        System.out.println("列表尾部的元素为:"+list.getLast());
    }
}

  下面是效果图:

在这里插入图片描述

  该代码中我还演示了LinkedList集合的其他方法,该方法时获取集合中元素个数的方法,下面就来介绍该方法。

1.3.5、获取元素个数的方法

  该方法的格式是:

  • int size()

  使用方法后会有一个int类型的返回值,代表:集合中的元素个数。

  具体的Java代码就不演示,就演示使用格式:

	LinkedList<Integer> list = new LinkedList<>();
	int number = list.size();
1.3.6、修改元素的方法

  修改元素的方法就一个:set方法,下面是方法格式:

  • E set​(int index, E element)

  使用该方法后会有一个泛型返回值,代表的是集合中被修改的旧元素,使用方法时需要传入两个参数:第一个是int类型的,代表你指定的位置,第二个是泛型的,代表你想要替换的新元素,方法作用是:将集合中你所指定位置的旧元素替换成你传入的新元素。

  以下是具体的Java代码:

public class Test4 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        Integer set = list.set(2, 5);
        for (int i = 0;i<list.size();i++){
            System.out.println("第"+(i+1)+"个元素为:"+list.get(i));
        }
        System.out.println("被替换的旧元素为:"+set);
    }
}

  以下是效果图:

在这里插入图片描述

1.3.7、删除元素的方法

   该类方法有以下几种:

  1. E remove()
  2. E removeFirst()
  3. E remove​(int index)
  4. boolean remove​(Object o)
  5. E removeLast()

  第一、二个方法效果一致,使用后会有一个泛型返回值,代表集合中被删除的旧元素,方法的作用是:删除并返回列表头部的元素;

  第二个方法使用后会有一个泛型返回值,代表集合中被删除的旧元素,使用时需要传入一个int类型的参数,代表:你所指定的位置,方法的作用是:删除并返回集合中你所指定位置的元素;

  第三个方法使用后会有一个boolean类型的返回值,如果值为true代表:在集合中有你指定的元素,如果值为false代表:集合中没有你指定的元素,使用时需要传入一个Object类型的参数,代表:你指定的元素,方法的作用是:删除集合中第一个和你指定的元素相同的元素

  第四种方法用后会有一个泛型返回值,代表集合中被删除的旧元素,方法的作用作用是:删除并返回列表尾部的元素;

  以下是具体的Java代码:

public class Test5 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        int a = 1;
        for (int i:list ) {
            System.out.println("集合删除前第"+a+"个元素为:"+i);
        }
        System.out.println("====================");
        Integer remove = list.remove(3);
        System.out.println("原集合下标为3的元素为:"+remove);
        Integer removeFirst = list.removeFirst();
        System.out.println("原列表头部的元素为:"+removeFirst);
        Integer removeLast = list.removeLast();
        System.out.println("原列表尾部的元素为:"+removeLast);
        a = 1;
        for (int i:list ) {
            System.out.println("集合删除后第"+a+"个元素为:"+i);
            a++;
        }
    }
}

  以下是效果图:

在这里插入图片描述

  LinkedList集合的方法就介绍这些,当然该集合的方法不止这一些,这些是我总结出来常用的方法,其他方法感兴趣的读者可以自行百度了解,我这里就不多做介绍了。

  关于LinkedList集合的相关知识就介绍到这,希望文章能帮到你们,谢谢阅读。

 

相关博文:“Java中的集合类:ArrayList”“Java多线程技术解析”

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值