基于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.对于随机访问 ...
随机推荐
- 末学者笔记--rpm和yum软件管理(Linux)
一.rpm简介 这是一个数据库管理工具,可以通过读取数据库,判断软件是否已经安装,如果已经安装可以读取出来所有文件的所在位置等,并可以实现删除这些文件. rpm:RPM is Redhat Packa ...
- sql 语句中count()有条件的时候为什么要加上or null
参考:https://blog.csdn.net/qq_32719287/article/details/79513164 1.sql 语句中count()有条件的时候为什么要加上or null. 如 ...
- tensorflow优化器-【老鱼学tensorflow】
tensorflow中的优化器主要是各种求解方程的方法,我们知道求解非线性方程有各种方法,比如二分法.牛顿法.割线法等,类似的,tensorflow中的优化器也只是在求解方程时的各种方法. 比较常用的 ...
- 强制.net 程序以32位模式运行
You can modify the PE header of the executable (using the "Corflags.exe" .NET Framework SD ...
- hbase读的性能优化
任何系统都会有各种各样的问题,有些是系统本身设计问题,有些却是使用姿势问题.HBase也一样,在真实生产线上大家或多或少都会遇到很多问题,有些是HBase还需要完善的,有些是我们确实对它了解太少.总结 ...
- 我的BO之强类型
弱类型的缺点 有些程序员对类型比较随意,从前端传来的数据,不管应该是什么类型,都以String接收.然后在什么地方转成应该有的类型则要"看心情",在Controller, Serv ...
- xxl-job调度中心配置以及常见错误
项目结构图 启动步骤: 1.检查 /xxl-job/xxl-job-admin/src/main/resources/xxl-job-admin.properties 下的JDBC链接.登录账号. 2 ...
- 【省选十连测之九】【DP】【组合计数去重】【欧拉函数】基本题
目录 题意: 输入格式: 输出格式: 数据范围: 思路: 嵌套题的转移 基本题的转移 Part1 Part2 Part3 代码 题意: 这是一个关于括号组合的题. 首先定义一道题是由'(',')',' ...
- U-Boot内存管理
如<Linux内核内存管理架构>一文中提到,linux内核中的内存管理支持内存地址映射.内存分配.内存回收.内存碎片管理.页面缓存等众多功能.但U-Boot做为启动引导程序,其核心功能就是 ...
- C#语言struct结构体适用场景和注意事项
在C#语言中struct结构体和class之间的区别主要是值类型和引用类型的区别,但实际上如果使用不当是非常要命的.从Win32时代过来的人对于struct一点不感觉陌生,但是却反而忽略了一些基本问题 ...