LinkedList特点和底层实现


title: JavaLinkedList特点和底层实现
date: 2020-03-25 22:25:50
author: JF
blog: https://www.huqifa.com/
tags:
- Java
- LinkedList
categories:
- Java


LinkedList特点和底层实现

LinkedList底层用双向链表实现的存储。

特点:查询效率低,增删效率高,线程不安全。

双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。

每个节点都应该有三部分内容:

class	Node{
		Node previous;	//前一个节点
		Object element;	//本节点保存的数据
		Node next;		//后一个节点
}

我们查看LinkedList的源码,可以看到里面包含了双向链表的相关代码:

package cn.LinkedList;
public class Node {
	Node previous;
	Node next;
	Object element;	
	public Node(Node previous,Node next,Object element) {
		super();
		this.previous = previous;
		this.next = next;
		this.element = element;
	}
	public Node(Object element) {
		super();
		this.element = element;
	}	
}
package cn.LinkedList;
/**
 * 自定义一个链表
 * @author HQF
 *
 */
public class LinkedList01 {
	private Node first;	//第一个节点
	private Node last;	//最后一个节点
	private int size;	//大小,有多少元素	
	//[]
	//['a','b','c']
	public void add(Object object) {
		Node node = new Node(object);	
		if (first==null) {
			first = node;
			last = node;
		}else {		
			node.previous = last;
			node.next = null;	
			last.next = node;
			last = node;
		}
	}
	@Override
	public String toString() {
		//[a,b,c]	first = a,	last = c;
		StringBuilder sBuilder = new StringBuilder("[");
		Node temp = first;
		while (temp!=null) {
			sBuilder.append(temp.element+",");
			temp = temp.next;
		}
		//setCharAt要使用单引号,否则会报错		sBuilder.setCharAt(sBuilder.length()-1, ']');
		return sBuilder.toString();
	}
	public static void main(String[] args) {
		LinkedList01 linkedList = new LinkedList01();
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
	System.out.println(linkedList);
	}
}
['a','b','c']

LinkedList_get查询_节点遍历

package cn.LinkedList;
/**
 * 自定义一个链表
 * @author HQF
 *
 */
public class LinkedList01 {
	private Node first;
	private Node last;
	private int size;
	
	//取出C元素,索引数为2
	public Object get(int index) {
		System.out.println(size);
		//异常处理
		if ((index<0)||(index>size-1)) {
			throw new RuntimeException("索引数字不合法"+index);
		}
		
		Node temp = null;
		
		//如果index大于size一半则从后便利,否则从前面遍历
		if (index<=(size>>1)) {//size>>1相当于除以2
			temp = first;
			for (int i = 0; i < index; i++) {
				temp = temp.next;
			}		
		}else {
			temp = last;
			for (int i = size-1; i > index; i--) {
				temp = temp.previous;
			}
		}
		return temp.element;
	}
	
	//[]
	//['a','b','c']
	public void add(Object object) {
		Node node = new Node(object);
		
		if (first==null) {
			first = node;
			last = node;
		}else {
			
			node.previous = last;
			node.next = null;
			
			last.next = node;
			last = node;
		}
		size++;
	}
	@Override
	public String toString() {
		//[a,b,c]	first = a,	last = c;
		StringBuilder sBuilder = new StringBuilder("[");
		Node temp = first;
		while (temp!=null) {
			sBuilder.append(temp.element+",");
			temp = temp.next;
		}
		//setCharAt要使用单引号,否则会报错
		sBuilder.setCharAt(sBuilder.length()-1, ']');
		return sBuilder.toString();
	}
	
	public static void main(String[] args) {
		LinkedList01 linkedList = new LinkedList01();
		
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		linkedList.add("d");
		linkedList.add("e");
		linkedList.add("f");
		
		System.out.println(linkedList);
		System.out.println(linkedList.get(4));
	}
}


LinkedList_remove移除节点

package cn.LinkedList;

/**
 * 自定义一个链表
 * @author HQF
 *
 */
public class LinkedList01 {
	private Node first;
	private Node last;
	private int size;
	
	//移除指定的元素
	public void remove(int index) {
		Node temp = getNode(index);
		
		if (temp!=null) {
			Node up = temp.previous;
			Node down = temp.next;
			
			if (up!=null) {
				up.next = down;
			}
			
			if (down!=null) {
				down.previous = up;
			}
			
			if (index == 0) {
				first = down;
			}
			
			if (index == size-1) {
				last = up;
			}
			size--;
		}
	}
	
	//取出C元素,索引数为2
	public Object get(int index) {
		System.out.println(size);
		//异常处理
		if ((index<0)||(index>size-1)) {
			throw new RuntimeException("索引数字不合法"+index);
		}
		Node temp = getNode(index);
		
		return temp!=null?temp.element:null;
	}
	
	public Node getNode( int index) {
		Node temp = null;
		
		//如果index大于size一半则从后便利,否则从前面遍历
		if (index<=(size>>1)) {//size>>1相当于除以2
			temp = first;
			for (int i = 0; i < index; i++) {
				temp = temp.next;
			}		
		}else {
			temp = last;
			for (int i = size-1; i > index; i--) {
				temp = temp.previous;
			}
		}
		return temp;
	}
	
	//[]
	//['a','b','c']
	public void add(Object object) {
		Node node = new Node(object);
		
		if (first==null) {
			first = node;
			last = node;
		}else {
			
			node.previous = last;
			node.next = null;
			
			last.next = node;
			last = node;
		}
		size++;
	}
	@Override
	public String toString() {
		//[a,b,c]	first = a,	last = c;
		StringBuilder sBuilder = new StringBuilder("[");
		Node temp = first;
		while (temp!=null) {
			sBuilder.append(temp.element+",");
			temp = temp.next;
		}
		//setCharAt要使用单引号,否则会报错
		sBuilder.setCharAt(sBuilder.length()-1, ']');
		return sBuilder.toString();
	}
	
	public static void main(String[] args) {
		LinkedList01 linkedList = new LinkedList01();
		
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		linkedList.add("d");
		linkedList.add("e");
		linkedList.add("f");
		
		System.out.println(linkedList);
		System.out.println(linkedList.get(4));
		linkedList.remove(0);
		System.out.println(linkedList);
	}
}

代码实现

[a,b,c,d,e,f]
6
e
[b,c,d,e,f]

LinkedList_插入节点

//添加节点
	public void add(int index,Object obj) {
		Node newNode = new Node(obj);
		Node temp = getNode(index);
		
		
		if (temp!=null) {
			Node up = temp.previous;
			
			up.next = newNode;
			newNode.previous = up;
			
			newNode.next = temp;
			temp.previous = newNode;
		}
	}
linkedList.add(3,"JF");
		System.out.println(linkedList);
//输出
[a,b,c,JF,d,e,f]

LinkedList完善_增加泛型

package cn.LinkedList;

/**
 * 自定义一个链表
 * @author HQF
 *
 */
public class LinkedList01<E> {
	private Node first;
	private Node last;
	private int size;
	
	//添加节点
	public void add(int index,E element) {//alt+shirt +r 替换
		Node newNode = new Node(element);
		Node temp = getNode(index);
		
		if (temp!=null) {
			Node up = temp.previous;
			
			up.next = newNode;
			newNode.previous = up;
			
			newNode.next = temp;
			temp.previous = newNode;
		}
	}
	
	//移除指定的元素
	public void remove(int index) {
		
		checkRange(index);
		
		Node temp = getNode(index);
		
		if (temp!=null) {
			Node up = temp.previous;
			Node down = temp.next;
			
			if (up!=null) {
				up.next = down;
			}
			
			if (down!=null) {
				down.previous = up;
			}
			
			if (index == 0) {
				first = down;
			}
			
			if (index == size-1) {
				last = up;
			}
			size--;
		}
	}
	
	//取出C元素,索引数为2
	public E get(int index) {
		System.out.println(size);

		Node temp = getNode(index);
		
		return temp!=null?(E)temp.element:null;
	}
	
	//处理索引的index合不合法
	private void checkRange(int index) {
		//异常处理
		if ((index<0)||(index>size-1)) {
			throw new RuntimeException("索引数字不合法"+index);
		}
	}
	
	private Node getNode( int index) {
		checkRange(index);
		
		Node temp = null;
		
		//如果index大于size一半则从后便利,否则从前面遍历
		if (index<=(size>>1)) {//size>>1相当于除以2
			temp = first;
			for (int i = 0; i < index; i++) {
				temp = temp.next;
			}		
		}else {
			temp = last;
			for (int i = size-1; i > index; i--) {
				temp = temp.previous;
			}
		}
		return temp;
	}
	
	//[]
	//['a','b','c']
	public void add(E element) {
		Node node = new Node(element);
		
		if (first==null) {
			first = node;
			last = node;
		}else {
			
			node.previous = last;
			node.next = null;
			
			last.next = node;
			last = node;
		}
		size++;
	}
	@Override
	public String toString() {
		//[a,b,c]	first = a,	last = c;
		StringBuilder sBuilder = new StringBuilder("[");
		Node temp = first;
		while (temp!=null) {
			sBuilder.append(temp.element+",");
			temp = temp.next;
		}
		//setCharAt要使用单引号,否则会报错
		sBuilder.setCharAt(sBuilder.length()-1, ']');
		return sBuilder.toString();
	}
	
	public static void main(String[] args) {
		LinkedList01<String> linkedList = new LinkedList01<>();
		
		linkedList.add("a");
		linkedList.add("b");
		linkedList.add("c");
		linkedList.add("d");
		linkedList.add("e");
		linkedList.add("f");
		
		System.out.println(linkedList);
		System.out.println(linkedList.get(4));
		linkedList.add(3,"JF");
		System.out.println(linkedList);
		System.out.println(linkedList.get(1));
	}
}

ArrayListLinkedList都是Java中常见的List集合类型,它们的底层实现方式不同,因此它们的性能特点也不同。 ArrayList底层使用数组来实现,因此它具有以下特点: 1. 随机访问效率高:由于ArrayList中的元素是按照顺序存储在数组中的,因此可以通过下标来快速访问任意一个元素,时间复杂度为O(1)。 2. 插入和删除效率低:由于ArrayList中的元素是存储在数组中的,因此在插入或删除元素时需要移动数组中的其他元素,时间复杂度为O(n)。 3. 空间浪费少:由于ArrayList中的元素是存储在数组中的,因此每个元素占用的空间是固定的,不会因为元素的增加而浪费空间。 LinkedList底层使用双向链表实现,因此它具有以下特点: 1. 随机访问效率低:由于LinkedList中的元素是按照指针链接的方式存储在链表中的,因此不能通过下标来快速访问任意一个元素,需要遍历链表,时间复杂度为O(n)。 2. 插入和删除效率高:由于LinkedList中的元素是存储在链表中的,因此在插入或删除元素时只需要修改指针的指向,时间复杂度为O(1)。 3. 空间浪费多:由于LinkedList中的元素是存储在链表中的,每个元素需要额外的指针来链接前后元素,因此每个元素占用的空间比ArrayList大。 需要根据具体的场景来选择使用ArrayList还是LinkedList。如果需要快速访问元素,应该选择ArrayList;如果需要频繁插入或删除元素,应该选择LinkedList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值