Java数据结构之LinkedList从链表到实现

 更新时间:2023年04月27日 11:17:08   作者:ZIYE_190  
LinkedList是Java中常用的数据结构之一,实现了链表的特性,支持快速添加、删除元素,可以用于实现队列、栈、双向队列等数据结构。LinkedList的内部实现采用了双向链表,其中每个节点都包含前驱节点和后继节点的引用,可以直接访问链表的头尾元素

1.ArrayList的缺陷

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
	// ...
	// 默认容量是10
	private static final int DEFAULT_CAPACITY = 10;
	//...
	// 数组:用来存储元素
	transient Object[] elementData; // non-private to simplify nested class access
	// 有效元素个数
	private int size;
	public ArrayList(int initialCapacity) {
		if (initialCapacity > 0) {
			this.elementData = new Object[initialCapacity];
		} else if (initialCapacity == 0) {
			this.elementData = EMPTY_ELEMENTDATA;
				} else {
						throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
				}
		} 
		// ...
}

由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构

2.LinkedList

LinkedList概念

LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。

在集合框架中,LinkedList也实现了List接口,具体如下:

说明:

  • LinkedList实现了List接口
  • LinkedList的底层使用了双向链表
  • LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  • LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

LinkedList的使用

LinkedList的构造

方法解释
LinkedList()无参构造
public LinkedList(Collection<? extends E> c)使用其他集合容器中元素构造List
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);
}

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 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位置插入元素elemSystem.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());
}

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();
}

3.链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  • 单向或者双向
  • 带头或者不带头
  • 循环或者非循环

虽然有这么多的链表的结构,但是我们重点掌握两种:

  • 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  • 无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

4.ArrayList和LinkedList的区别

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

到此这篇关于Java数据结构之LinkedList从链表到实现的文章就介绍到这了,更多相关Java LinkedList内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot 使用 Ehcache 作为缓存的操作方法

    SpringBoot 使用 Ehcache 作为缓存的操作方法

    这篇文章主要介绍了SpringBoot 如何使用 Ehcache 作为缓存,我们通过添加 Ehcache 依赖、创建 Ehcache 配置文件并在 Spring Boot 应用程序的配置文件中启用 Ehcache 缓存,来配置 Ehcache 缓存,需要的朋友可以参考下
    2023-06-06
  • Java的常用包

    Java的常用包

    本文主要对Java的常用包进行一一介绍。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 详解Java正则表达式中Pattern类和Matcher类

    详解Java正则表达式中Pattern类和Matcher类

    java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。包括两个类Pattern和Matcher Pattern,Pattern是一个正则表达式经编译后的表现模式。Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。
    2016-12-12
  • java实现的根据概率随机中奖测试类

    java实现的根据概率随机中奖测试类

    这篇文章主要介绍了java实现的根据概率随机中奖测试类,结合完整实例形式详细分析了java随机数实现概率运算相关操作技巧,需要的朋友可以参考下
    2019-09-09
  • 深入理解Java中的volatile关键字(总结篇)

    深入理解Java中的volatile关键字(总结篇)

    volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。这篇文章主要介绍了Java中的volatile关键字,需要的朋友可以参考下
    2018-10-10
  • Java数组(Array)最全汇总(上篇)

    Java数组(Array)最全汇总(上篇)

    这篇文章主要介绍了Java数组(Array)最全汇总(上篇),本文章内容详细,通过案例可以更好的理解数组的相关知识,本模块分为了三部分,本次为上篇,需要的朋友可以参考下
    2023-01-01
  • kafka消费不到数据的排查过程

    kafka消费不到数据的排查过程

    这篇文章主要介绍了kafka消费不到数据的排查过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • java使用poi生成excel的步骤

    java使用poi生成excel的步骤

    2010以上格式使用XSSFWorkBook对象, 2003格式使用HSSFWorkBook对象, 其他对象操作基本一样,本文重点给大家介绍java使用poi生成excel的相关知识,感兴趣的朋友一起看看吧
    2022-04-04
  • springboot中RestTemplate配置HttpClient连接池详解

    springboot中RestTemplate配置HttpClient连接池详解

    这篇文章主要介绍了springboot中RestTemplate配置HttpClient连接池详解,这些Http连接工具,使用起来都比较复杂,如果项目中使用的是Spring框架,可以使用Spring自带的RestTemplate来进行Http连接请求,需要的朋友可以参考下
    2023-11-11
  • 实例解析Java中的构造器初始化

    实例解析Java中的构造器初始化

    这篇文章主要通过实例解析Java中的构造器初始化,代码很简单,叙述很明确,需要的朋友可以了解下。
    2017-09-09

最新评论