基于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.对于随机访问 ...
随机推荐
- 处理 oracle 数据库导入报错“IMP-00058: 遇到 ORACLE 错误 942”
在导入数据文件的时候出现了下图错误: 经过多次百度搜索问题.得知问题错误方向: 仔细的查询了被导入数据的数据库的版本: 而 被导入的数据包 dmp 文件是从 oracle11g r2的版本导出的. 所 ...
- MIUI11系统怎么样启用root权限的教程
MIUI11系统如何启用了ROOT超级权限?做开发的人都知道,安卓机器有ROOT超级权限,一旦手机启用了root相关权限,可以实现更多的功能,举个例子做开发的人公司的营销部门的妹纸,使用较多营销工具都 ...
- IDEA下运行 mybatis报错 Parameter 'arg0' not found. Available parameters are [autoRecharge, id, param1, param2]
电脑换系统之后重新安装一了 一下idea 项目运行时出现了以下错误, [autoRecharge, id, param1, param2] 或 [arg0, id, arg1, param2] 参考地 ...
- ****微信小程序架构解析
| 导语 微信小程序的公测掀起了学习小程序开发的浪潮,天生跨平台,即用即走.媲美原生体验.完善的文档.高效的开发框架,小程序给开发者带来了很多惊喜.通过这篇文章和大家一起分析小程序的架构,分享开发 ...
- 分享:使用 TypeScript 编写的游戏代码
<上篇博客>我写出了我一直期望的 JavaScript 大型程序的开发模式,以及 TS(TypeScript) 的一些优势.博客完成之后,我又花了一天时间试用 TS,用它来重构之前编写的一 ...
- IntelliJ IDEA添加JUnit单元测试
使用idea IDE 进行单元测试,首先需要安装JUnit 插件. 1.安装JUnit插件步骤 File-->settings-->Plguins-->Browse reposito ...
- kafka 客户端 producer 配置参数
属性 描述 类型 默认值 bootstrap.servers 用于建立与kafka集群的连接,这个list仅仅影响用于初始化的hosts,来发现全部的servers.格式:host1:port1,ho ...
- 三大家族(offset、scroll、client)
offset.scroll.client三大家族 offset家族 offsetWidth 与 offsetHeight offset 偏移 用于获取元素自身的位置和大小 offsetWidth和of ...
- php换行和<br />互转
使用场景:在后台处理textarea换行的时候出现了问题, textarea里面的换行就是/n, 在textarea里面是有换行效果的,但是输出到其它地方没有效果,这时候就要用到PHP的神奇的nl2b ...
- 结对开发项目--石家庄地铁web版
一.功能要求 1.数据库设计:将石家庄地铁线路图的各个线路,各个站点,换乘信息等用数据库的形式保存起来,应该保存的信息有 {线路号,线路的各个站名,车站的换乘信息}. 2.站点查询:用户可以输入任一一 ...