ArrayList
底层数据结构是数组
内存是连续的
有索引
查询速度快
增删速度慢
线程不安全的集合
默认无参构造时会创建一个长度为0的数组
第一次使用add,扩容为10
每次扩容是原来容量+原来容量/2
以下是手写实现方式,如有bug请指正
package cn.javasm.test;
import java.util.Arrays;
import java.util.Objects;
/**
* @className: ArrayListDemo
* @description: 模拟ArrayList
* @author: gfs
* @date: 2024/12/11 14:40
* @version: 0.1
* @since: jdk11
*/
public class ArrayListDemo {
// 存储数据的数组
private String[] data;
// 元素的实际个数
private int size;
// 定义无参构造
public ArrayListDemo(){
// 默认的初始容量
data = new String[10];
}
public int length(){
return data.length;
}
@Override
public String toString() {
String str = "[";
for (int i = 0; i < size - 1; i++) {
str += data[i] + ", ";
}
if(size > 0)
str += data[size - 1];
str += "]";
return str;
}
// 定义有参构造,根据用户传入的参数使用初始容量
public ArrayListDemo(int len){
// 判断参数是否合法
if (len < 0) throw new IllegalArgumentException();
data = new String[len];
}
/**
* 判断是否需要扩容
*/
private void Expansion() {
// 判断是否需要扩容
if (size >= data.length){
if (data.length > 1){
data = Arrays.copyOf(data,data.length + ((data.length) >> 1));
}else {
data = Arrays.copyOf(data,data.length + 1);
}
}
}
/**
* 判断索引是否符合规范
* @param index
*/
private void judgeIndex(int index) {
if(index > size || index < 0) throw new IndexOutOfBoundsException("您输入的索引不对");
}
/**
* 添加元素方法
* @param str 添加的元素
*/
public void add(String str){
//判断是否需要扩容
Expansion();
// 添加元素
data[size++] = str;
}
/**
* 根据索引插入到数组中
* @param index
* @param str
*/
public void add(int index,String str){
// 判断索引是否符合规范
judgeIndex(index);
// 判断是否要扩容
Expansion();
// 如果是实际长度+1的索引,直接放入
if(index == size){
data[size++] = str;
return;
}
for (int i = size; i >= index; i--) {
data[i+1] = data[i];
}
data[index] = str;
size++;
}
/**
*
* 清空数组
*/
public void clear(){
data = new String[10];
size = 0;
}
/**
* 查询数组中是否包含s
* @param s
* @return
*/
public boolean contains(String s){
return indexOf(s) != -1;
}
/**
* 获取数组对应索引的值
* @param index
* @return
*/
public String get(int index){
//判断index 是否合法
if(index >= size || index < 0) throw new IndexOutOfBoundsException("数组越界了");
return data[index];
}
public void set(int index , String s){
//判断index 是否合法
judgeIndex(index);
data[index] = s;
}
/**
* 查询数组中第一次出现指定元素的索引,并返回对应索引
* @param s
* @return
*/
public int indexOf(String s){
for (int i = 0; i < size; i++) {
if(Objects.equals(s,data[i])) return i;
}
return -1;
}
/**
* 查询数组中最后一次出现指定元素的索引,并返回对应索引
* @param s
* @return
*/
public int lastIndexOf(String s){
for (int i = size; i > 0; i--) {
if(data[i] == s) return i;
}
return -1;
}
/**
* 查询数组是否为空
* @return
*/
public boolean isEmpty(){
return size == 0;
}
/**
* 移除数组中第一次出现指定的元素
* @param s
* @return
*/
public boolean remove(String s){
int i = indexOf(s);
if(i != -1) {
for (int j = i; j < size - 1; j++) {
data[j] = data[j + 1];
}
size--;
data[size] = null;
return true;
}else {
return false;
}
}
/**
* 移除数组中出现指定的元素
* @param s
* @return
*/
public boolean removeAll(String s){
boolean isFlag = false;
while (remove(s)){
isFlag = true;
}
return isFlag;
}
/**
* 返回数组实际参数的个数
* @return
*/
public int size(){
return size;
}
public ArrayListDemo subList(int fromIndex,int toIndex){
if(fromIndex >= toIndex || fromIndex < 0 || toIndex > size) throw new IllegalArgumentException("索引不正确");
ArrayListDemo sublist = new ArrayListDemo(toIndex - fromIndex);
System.arraycopy(data,fromIndex,sublist,0,toIndex - fromIndex);
sublist.size = toIndex - fromIndex;
return sublist;
}
public void trimToSize(){
data = Arrays.copyOf(data,size);
}
}
LinkedList
底层数据结构是双向链表
内存是不连续的
无索引
查询速度慢
增删速度快
本质上一个对象是一个元素
以下是手写实现方式,如有bug请指正
package cn.javasm.demo;
import java.util.Objects;
/**
* @className: LinkedList
* @description:
* @author: wj
* @date: 2024/12/12 10:30
* @version: 0.1
* @since: jdk11
*/
public class LinkedListDemo {
// 实际元素个数
private int size;
// 头节点
private Node first;
// 尾节点
private Node last;
public void add(String str){
Node node = new Node(str,null,null);
if(size == 0){
// 第一个插入的话
this.first = node;
}else {
node.prev = this.last;
node.prev.next = node;
}
this.last = node;
size++;
}
public Node get(int index){
if(index >= size || index < 0) throw new IndexOutOfBoundsException("输入的索引不正确");
Node node = first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
public int indexOf(String s){
Node node = first;
for (int i = 0; i < size; i++) {
if(Objects.equals(s,node.data)) return i;
node = node.next;
}
return -1;
}
public boolean contains(String s){
return indexOf(s) != -1;
}
public void add(int index,String str){
if(index > size || index < 0) throw new IndexOutOfBoundsException("输入的索引不正确");
if(index == size) {
add(str);
return;
}
Node node = get(index);
Node addNode = new Node(str,null,null);
if(this.first == node){
node.prev = addNode;
addNode.next = node;
this.first = addNode;
}else {
// 将加入的新地址更换
addNode.next = node;
addNode.prev = node.prev;
node.prev.next = addNode;
node.prev = addNode;
}
size++;
}
public LinkedListDemo remove(){
if(size != 0){
first = first.next;
first.prev = null;
size--;
}
return this;
}
public LinkedListDemo remove(int index){
Node node = get(index);
if(node == first){
remove();
return this;
}else if(node == last){
last.prev.next = null;
last.prev = last;
size--;
}else {
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = null;
node.next = null;
size--;
}
return this;
}
public boolean isEmpty(){
return size == 0;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder("[");
Node node = first;
for (int i = 0; i < size; i++) {
if(i != size-1){
str.append(node.data).append(", ");
node = node.next;
}else {
str.append(node.data);
}
}
str.append("]");
return str.toString();
}
public void clear(){
first = null;
last = null;
size = 0;
}
public int size(){
return size;
}
public LinkedListDemo subList(int fromIndex,int toIndex){
if(fromIndex > toIndex || fromIndex < 0 || toIndex > size) throw new IndexOutOfBoundsException();
LinkedListDemo linkedListDemo = new LinkedListDemo();
Node node = first;
for (int i = 0; i < size; i++) {
if(i >= fromIndex && i < toIndex) {
linkedListDemo.add(node.data);
}
node = node.next;
}
return linkedListDemo;
}
public String set(int index, String str){
Node node = get(index);
node.data = str;
return str;
}
private class Node {
// 数据
private String data;
// 前一个节点
private Node prev;
// 后一个节点
private Node next;
public Node(String data, Node prev, Node next) {
this.data = data;
this.prev = prev;
this.next = next;
}
}
}
但不论增删还是查询效率其实ArrayList更高,因为每次LinkedList添加元素时都会创建一个对象