基于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.对于随机访问 ...
随机推荐
- Vue过滤器使用
格式(一个过滤器):{{ 'msg' | filterA }} (多个过滤器):{{ 'msg' | filterA | filterB }} window.onload =function(){ / ...
- linux环境给mongodb创建索引
首先我们来了解索引,如果有基础的可以直接看最后面的操作. 可参照 DoNotStop 的CSDN 博客 ,全文地址请点击: https://blog.csdn.net/u013725455/artic ...
- PHP 报错--Array to string conversion,请用print_r() 来输出数组
报错如下: 原因:数组不能用 echo 来输出 解决办法:print_r() 来输出数组 解决办法:var_dump() 来查看数据类型
- 公司外网测试服务器 redis 被攻击复盘
最近 公司外网的测试的 redis 服务器被攻击,最开始是用 docker 搭建的 直接裸奔在外网,任何域名都可以通过 ip+6379来访问,最开始想的是测试服务器也没有啥,后面直接就被人登陆进去改了 ...
- 做IT,必备的安全知识!
以前的认知 以前刚接触IT行业,而我身为运维,我以为我所需要做的安全就是修改服务器密码为复杂的,ssh端口改为非22,还有就是不让人登录服务器就可以保证我维护的东西安全. 现在的认知 工作也好几年了, ...
- c++继承学习
继承分类: 虚表继承 class D{ public : d(){ } ~d(){ } private: }; 单重继承 class D{ public : d(){ } ~d(){ } privat ...
- Ubuntu zsh shell 一站式解决方案
#!/bin/bash sudo apt-get install zsh python -y sudo apt-get install python-pip -y sh -c "$(curl ...
- [jzoj]3468.【NOIP2013模拟联考7】OSU!(osu)
Link https://jzoj.net/senior/#main/show/3468 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: ...
- NOIP-珠心算
题目描述 珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术.珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及. 某学校的珠心算老师采用一种快速考察珠心算加 ...
- RHEL系统初始化步骤
1.配置网络 ##初始化网络(可在虚拟网络编辑器查看自己的网段) ##方法一:静态初始化 read -p "输入你当前Linux的IP地址:" ip ETH=` ifconfig ...