基于Java的ArrayList和LinkedList的实现与总结
一、定义MyList接口,包含列表常见方法:
import java.util.Iterator; /**
* 线性表(列表)的接口定义
*/
public interface MyList<T> extends Iterator<T> { /** 新增一个元素 */
void add(T element); /** 删除相同元素 */
void delete(T element); /** 根据索引删除元素 */
void delete(int index); /**
* 将指定索引位置的元素替换成新元素
*
* @param index
* @param newElement
*/
void update(int index, T newElement); /**
* 当前列表中是否含有target这个元素
*
* @param target
* @return
*/
boolean contains(T target); /**
* 返回指定索引处的元素
*
* @param index
* @return
*/
T at(int index); /**
* 查找element的索引,如果没有返回-1
*
* @param element
* @return
*/
int indexOf(T element); }
二、实现ArrayList类:
/**
* 用顺序存储(数组)方式来实现列表
*/
public class MyArrayList<T> implements MyList<T> {
private T[] elements;// 真正存储元素的底层结构 private int size = 0;// 元素个数 private int capacity = 10;// 容量 public MyArrayList(int capacity) {
this.capacity = capacity;
elements = (T[]) new Object[capacity];
} public MyArrayList() {
elements = (T[]) new Object[capacity];
} @Override
public void add(T element) {
if (size == capacity) {// 扩容
capacity *= 2;// 增加一倍的容量
T[] newArr = (T[]) new Object[capacity];// 新建一个数组
for (int i = 0; i < size; i++) {
newArr[i] = elements[i];
}
elements = newArr;// 把旧的那个柜子扔掉
}
elements[size++] = element;
} @Override
public void delete(T element) {
int index = indexOf(element);
if (index >= 0) {
delete(index);
}
} @Override
public void delete(int index) {
// 重新调整空间
for (int i = index; i < size - 1; i++) {
elements[i] = elements[i + 1];
}
elements[size - 1] = null;
size--;
} @Override
public void update(int index, T newElement) {
elements[index] = newElement;
} @Override
public boolean contains(T target) {
return indexOf(target) >= 0;
} @Override
public T at(int index) {
return elements[index];
} @Override
public int indexOf(T element) {
for (int i = 0; i < size; i++) {
if (elements[i].equals(element)) {
return i;
}
}
return -1;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elements[i] + (i == size - 1 ? "" : " , "));
}
sb.append("]");
return sb.toString();
} //
@Override
public boolean hasNext() {
return false;
} @Override
public T next() {
return null;
}
}
三、链表结点类:
/*节点*/
public class ListNode<T> {
T data;
ListNode<T> pre;
ListNode<T> next; // next 实际存的是下一个节点 重要理解 public ListNode(T data) {
this.data = data;
} public T getData() {
return data;
} public ListNode<T> getPre() {
return pre;
} public void setNext(ListNode<T> next) {
this.next = next;
} public void setPre(ListNode<T> pre) {
this.pre = pre;
} public ListNode<T> getNext() {
return next;
}
}
四、单链表实现:
public class SingleLinkedList<T> implements MyList<T> {
private ListNode<T> first; // 头节点 head
private ListNode<T> last; // 尾节点
private int size;
@Override
public void add(T element) {
if (first == null) {
first = new ListNode(element);
last = first;
} else {
last.next = new ListNode(element); // next 实际存的是下一个节点 重要理解
last = last.next;
}
size++;
}
@Override
public void delete(T element) {
ListNode p = first;
ListNode pre = null;
while (p != null) {
if (p.data.equals(element)) {
if (p == first)
first = first.next;
else
pre.next = p.next;
size--;
break;// 注意这里
}
pre = p;
p = p.next;
}
}
// 链表删除
// 参数为索引
@Override
public void delete(int index) {
if (index < 0 || index >= size) {
return;// 啥也不干
}
int i = 0;// 指针指向的节点的索引
ListNode p = first;
ListNode pre = null;
while (p != null) {
if (i == index) {
if (p == first)
first = first.next;
else
pre.next = p.next;
break;// 注意这里
}
pre = p;
p = p.next;
i++;
}
size--;
}
@Override
public void update(int index, T newElement) {
if (index < 0 || index >= size) {
return;// 啥也不干
}
int i = 0;// 指针指向的节点的索引
ListNode p = first;
while (p != null) {
if (i == index) {
p.data = newElement;
}
p = p.next;
i++;
}
}
@Override
public boolean contains(T target) {
ListNode p = first;
while (p != null) {
if (p.data.equals(target)) {
return true;
}
p = p.next;
}
return false;
}
// 返回索引所在的data
@Override
public T at(int index) {
if (index < 0 || index >= size) {
return null;
}
int i = 0;// 指针指向的节点的索引
ListNode<T> p = first;
while (p != null) {
if (i == index) {
return p.data;
}
p = p.next;
i++;
}
return null;
}
@Override
public int indexOf(T element) {
int i = 0;// 指针指向的节点的索引
ListNode p = first;
while (p != null) {
if (p.data.equals(element)) {
return i;
}
p = p.next;
i++;
}
return -1;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
ListNode p = first;
while (p != null) {
sb.append(p.data);
if (p.next != null)
sb.append(",");
p = p.next;
}
sb.append("]");
return sb.toString();
}
@Override
public boolean hasNext() {
return false;
}
@Override
public T next() {
return null;
}
}
五、双链表实现:
import java.util.Iterator;
public class DoubleLinkedList<T> implements MyList<T> {
// 多了两个没有数据的头节点和尾节点 哑元
protected ListNode<T> first = new ListNode(null);
protected ListNode<T> last = new ListNode(null);
protected int size;
public int getSize() {
return size;
}
public DoubleLinkedList() {
first.next = last;
last.pre = first;
}
@Override
public void add(T element) {
ListNode<T> newNode = new ListNode(element);
last.pre.next = newNode;
newNode.next = last;
newNode.pre = last.pre;
last.pre = newNode;
size++;
}
@Override
public void delete(T element) {
ListNode<T> p = first.next;
while (p != last) {
if (p.data.equals(element)) {
p.pre.next = p.next;
p.next.pre = p.pre;
p.next = null;
p.pre = null;
size--;
break;
}
p = p.next;
}
}
@Override
public void delete(int index) {
if (index < 0 || index >= size) {
return;// 啥也不干
}
int i = 0;// 指针指向的节点的索引
ListNode p = first.next;
while (p != last) {
if (i == index) {
p.pre.next = p.next;
p.next.pre = p.pre;
p.next = null;
p.pre = null;
size--;
break;// 注意这里
}
p = p.next;
i++;
}
}
@Override
public void update(int index, T newElement) {
if (index < 0 || index >= size) {
return;// 啥也不干
}
int i = 0;// 指针指向的节点的索引
ListNode p = first.next;
while (p != last) {
if (i == index) {
p.data = newElement;
}
p = p.next;
i++;
}
}
@Override
public boolean contains(T target) {
ListNode p = first.next;
while (p != last) {
if (p.data.equals(target)) {
return true;
}
p = p.next;
}
return false;
}
@Override
public T at(int index) {
if (index < 0 || index >= size) {
return null;
}
int i = 0;// 指针指向的节点的索引
ListNode<T> p = first.next;
while (p != last) {
if (i == index) {
return p.data;
}
p = p.next;
i++;
}
return null;
}
@Override
public int indexOf(T element) {
int i = 0;// 指针指向的节点的索引
ListNode<T> p = first.next;
while (p != last) {
if (p.data.equals(element)) {
return i;
}
p = p.next;
i++;
}
return -1;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
ListNode p = first.next;
while (p != last) {
sb.append(p.data);
if (p.next != last)
sb.append(",");
p = p.next;
}
sb.append("]");
return sb.toString();
}
// 实现迭代器 MyList 继承Iterator<T>这个接口
private ListNode now = first;
@Override
public boolean hasNext() {
return now.next != last;
}
@Override
public T next() {
ListNode<T> next = now.next;
now = now.next;
return next.data;
}
}
六、Java ListApi的基本使用:
import java.util.*;
public class ListApiDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list = new LinkedList<>();
list.add("adnda");
list.add("xyz");
list.add("def");
list.remove("");
// ......
Collections.sort(list);
System.out.println(list);
List<Student> list1 = new ArrayList<>();
list1.add(new Student("zhangsan", 10));
list1.add(new Student("lsii", 20));
list1.add(new Student("wangwu", 40));
list1.add(new Student("wangsu", 30));
Collections.sort(list1, (o1, o2) -> {
return o1.getAge() - o2.getAge();
});
System.out.println(list1);
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
System.out.println("===============");
for (Student stu : list1) {
System.out.println(stu);
}
System.out.println("++++++++++++++++++++");
Iterator<Student> iterator = list1.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
七、ArrayList和LinkedList总结:
1、ArrayList和LinkedList都是实现了List接口的容器类,用于存储一系列的对象引用。他们都可以对元素的增删改查进行操作。
2、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
3、对ArrayList和LinkedList的空间复杂度而言,对 ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Node对象。ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间 。
4、对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。 ArrayList可以根据索引直接算出地址。
5、在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
6、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。对于查找和修改操作,如果按照索引查找和修改,ArrayList优于LinedList,如果按照内容来进行查找和修改,ArrayList和LinedList所花费的时间差不多。
7、LinkedList不支持高效的随机元素访问。 比如二分查找就是才有的随机策略,就不适合采用LinkedList,适合ArrayList。
可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中 间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。 所以,如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是对其它指定位置的插入、删除操作,最好选择LinkedList。
注意:next 实际存的是下一个节点 个人重要理解。
基于Java的ArrayList和LinkedList的实现与总结的更多相关文章
- Java中ArrayList与LinkedList的区别
Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...
- java中ArrayList 和 LinkedList 有什么区别
转: java中ArrayList 和 LinkedList 有什么区别 ArrayList和LinkedList都实现了List接口,有以下的不同点:1.ArrayList是基于索引的数据接口,它的 ...
- Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]
Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...
- Java中arraylist和linkedlist源代码分析与性能比較
Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arra ...
- Java基础-ArrayList和LinkedList的区别
大致区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为Lin ...
- Java中ArrayList和LinkedList差别
一般大家都知道ArrayList和LinkedList的大致差别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机訪问get和set.A ...
- JAVA中ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题
近期在做一个对接京东的电商平台,所以对各个地方的效率考虑的比较多,今天深挖了一下ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题,首先说一下两种 ...
- Java基础——ArrayList与LinkedList(一)
一.定义 ArrayList和LinkedList是两个集合类,用于储存一系列的对象引用(references). 引用的格式分别为: ArrayList<String> list = n ...
- Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度
一般大家都知道ArrayList和LinkedList的大致区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问 ...
随机推荐
- 初识C语言(六)
数组 程序中需要容器,该容器有点特殊,它在程序中是一块连续的,大小固定并且里面的数据类型一致的内存空间,它的名字叫数组. 声明一个数组: 数据类型 数组名称[长度]; C语言中的数组初始化是有三种形式 ...
- Appium 测试微信小程序 Webview
通过微信打开debugx5.qq.com,或者直接扫下面二维码 勾选[打开TBS内核Inspector调试功能] Chrome查看页面元素 手机连接电脑,查看是否连接成功.如下展示设备号则为连 ...
- MySQL-连表查询联系
链接 1.将老师的姓名和所教课程罗列出来 SELECT teacher_id,tname,cname FROM course LEFT JOIN teacher ON course.`teacher_ ...
- .net core读取json配置文件
一.新建.net core控制台程序 二.通过Nuget引入 Microsoft.Extensions.Configuration和microsoft.extensions.configuration ...
- spring boot 配置 fastjson 替代 Jackson (并解决返回字符串带双引号问题)
注:以我遇到的情况,只要发出的请求参数是map格式的,都会在前后多加一个双引号 以下代码有两个功能:1.FastJson 替换 Spring 自带的 Jackson 2.解决返回的字符串带双引号问题 ...
- 阿里云+WordPress搭建个人博客
搭建过程: 第一步:首先你需要一台阿里云服务器ECS,如果你是学生,可以享受学生价9.5元/月 (阿里云翼计划:https://promotion.aliyun.com/ntms/act/campus ...
- OpenSSL MD5 API
#include <stdlib.h> #define _GNU_SOURCE /* for getline API */ #include <stdio.h> /* Open ...
- day23.面向对象之继承
1.什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 class A ...
- 一种DTO的规划方案
现在以网页发布的软件非常普遍,叫BS模式.前后端分离也是大趋势,或者说逐渐普及开来,深受前后端程序员的喜爱,我还是习惯以程序员来泛称所有软件制作者.后端需要把数据传送给前端,往往是通过DTO的序列化来 ...
- ARP欺骗配置及演示过程
目录 环境 软件 网络拓扑图 配置流程 配置构思 具体流程 问题 演示过程 状态 检查Attack前centOS7_1的ARP地址表 在kali上输入以下命令发动攻击 此时查看centOS7_1的AR ...