模拟ArrayLIst的底层实现

package com.tedu.api04.list;

import java.util.Objects;

/**
* @author LIGENSEN
* Date: 2023/7/20 11:35
*/
public class ArrayListDemo {
public static void main(String[] args) {
ArrList<String> list=new ArrList<>(1);
list.add("a");
list.add("b");
list.add("c");
list.add("f");
list.add("c"); // list.add(0,"d");
// list.clear();
// list.add(4,"e");
// list.add(2,"f");
// list.add(4,"e");
System.out.println(list.indexOf("d"));
System.out.println(list.contains("c"));
System.out.println(list.get(2));
System.out.println(list.isEmpty());
System.out.println(list.lastIndexOf("c"));
list.remove(3);
list.remove("a");
list.set(1,"cc");
System.out.println(list.subList(0, 1));
list.toArray(); System.out.println(list);
}
} /**
* 用数组来实现 ArrList
* 集合里面可以用 Object[] 存任意的数据
*
* @param <E>
*/
//模拟:用数组来实现ArrayList
class ArrList<E>{
//数组
private Object[] arr;
//数组元素个数
private int size;
//初始容量
private int initialCapacity; public ArrList(){
arr=new Object[10];
}
//指定容量
public ArrList(int initialCapacity){
// 初始容量必须 > 0
if(initialCapacity < 0){
throw new IllegalArgumentException("非法参数异常");
}
this.initialCapacity=initialCapacity;
arr=new Object[this.initialCapacity];
} //添加元素
public void add(E e){
//判断是否需要扩容
if(size == arr.length)grow();
//向第size位置上添加元素
arr[size++]=e;
} //在指定的位置插入指定的元素
public void add(int index,E e){
//判断下标是否越界
if(index < 0 || index > size)
throw new IndexOutOfBoundsException("Index:" + index +",Size" + size);
//判断是否需要扩容
if(size == arr.length) grow();
//移动元素
/*for (int i = size-1; i >= index ; i--) {
arr[i+1]=arr[i];
}*/
System.arraycopy(arr,index,arr,index+1,size-index);
arr[index]=e;
size++;
} //清空集合
public void clear(){
//清空每一个元素对应的引用
for (int i = 0; i < size; i++) {
arr[i]=null;
}
//重构数组
arr=new Object[initialCapacity];
//元素个数归零
size=0;
} //获取指定元素第一次出现的下标
public int indexOf(E e){
//遍历集合
for (int i = 0; i < size; i++) {
/**
* 第一个 == 判断引用类型是够相等
* arr[i].equals(e) 只能引用类型调用,判断的是值相等(重写Object 中的 equals之后)
*/
//if(arr[i] == e || arr[i] != null && arr[i].equals(e))
if(Objects.equals(arr[i],e))
return i;
}
//如果整个循环结束,都没有return,说明没找到
return -1;
}
//判断是否包含指定元素
public boolean contains(E e){
return indexOf(e) >= 0;
} //判断越界
private void outBounds(int index){
if(index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index:"+index+",Size"+size);
} //获取指定位置上的元素
public E get(int index){
//判断越界
outBounds(index);
//获取指定的元素
return (E)arr[index]; } //判断集合是否为空
public boolean isEmpty(){
return size<=0;
} //获取指定元素最后一次出现的下标
public int lastIndexOf(E e){
for (int i = size-1; i >= 0 ; i--) {
if (Objects.equals(arr[i],e))return i;
}
return -1;
} //删除指定下标上的元素
public void remove(int index){
//判断越界
outBounds(index);
//后边的元素覆盖前面的元素
/*for (int i = index+1; i < size; i++) {
arr[i-1]=arr[i];
}*/
System.arraycopy(arr,index+1,arr,index,size-(index+1));
size--;
} //删除指定元素
public void remove(E e){
//获取第一次出现的位置
int index = indexOf(e);
//判断是否存在
if(index >= 0)remove(index);
} //替换指定位置上的元素
public void set(int index,E e){
//越界
outBounds(index);
//替换
arr[index]=e;
} //获取元素个数
public int size(){
return size;
} //截取子列表
public ArrList<E> subList(int fromIndex,int toIndex){
//判断下标范围
if(fromIndex < 0 || toIndex > size || fromIndex > toIndex)
throw new IllegalArgumentException();
//截取字列表
ArrList<E> sub=new ArrList<>();
for (int i = fromIndex; i < toIndex; i++) {
sub.add((E)arr[i]);
}
return sub;
} //转为数组
public Object[] toArray(){
//新建数组
Object[] newArray=new Object[size];
//赋值元素
System.arraycopy(arr,0,newArray,0,size);
return newArray;
} //扩容
private void grow(){
//计算新数组的容量
int capacity=size;
if(size < 2)
capacity +=1;
else
capacity=size + (size >> 1);
//构建新的数组
Object[] arr=new Object[capacity];
//将原来数组中的元素赋值到新的数组中
System.arraycopy(this.arr,0,arr,0,size);
this.arr=arr;
} //转为字符传
@Override
public String toString() {
//判断集合是否为空
if(size <= 0) return "[]";
//拼接元素
StringBuilder sb=new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(arr[i]).append(", ");
}
//转为字符串
String str = sb.toString();
//去掉尾部的", "
str=str.substring(0,str.length()-2);
//返回
return str += "]";
}
}

运行结果如下:

模拟ArrayList(顺序表)的底层实现的更多相关文章

  1. 三 模拟实现顺序表ArrayList

    /** * 顺序表,重点是数组动态扩容,插入 * 底层采用数组,长度可以动态变化,此处采用增长一倍 *  java.util.ArrayList每次增长50% *  int newCapacity = ...

  2. [Java算法分析与设计]--线性结构与顺序表(List)的实现应用

    说到线性结构,我们应该立马能够在脑子里蹦出"Array数组"这个词.在Java当中,数组和对象区别基本数据类型存放在堆当中.它是一连串同类型数据存放的一个整体.通常我们定义的方式为 ...

  3. ArrayList和LinkedList的底层代码实现思想

    ArrayList是Java众多集合类中的一个,实现List接口,List的父接口是Collection.ArrayList底层的数据结构是线性表中的顺序表,底层是一个长度可以动态增长的数组.数组有很 ...

  4. Java实现顺序表

    利用顺序存储结构表示的顺序表称为顺序表. 它用一组连续的地址存储单元一次存放线性表中的数据元素. 顺序表的实现是数据结构中最简单的一种. 由于代码中已经有详细注释,代码外不再阐述. 下次再陈上关于顺序 ...

  5. 数据结构之线性顺序表ArrayList(Java实现)

    一.ListMe接口: import java.util.ArrayList; //实现线性表(顺序表和链表)的接口://提供add get isEmpty size 功能public interfa ...

  6. 自定义顺序表ArrayList

    1.简介 顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素.使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通 ...

  7. Java数据结构-线性表之顺序表ArrayList

    线性表的顺序存储结构.也称为顺序表.指用一段连续的存储单元依次存储线性表中的数据元素. 依据顺序表的特性,我们用数组来实现顺序表,以下是我通过数组实现的Java版本号的顺序表. package com ...

  8. (java实现)顺序表-ArrayList

    什么是顺序表 顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构. 在使用顺序表存储数据前,会先申请一段连续的内存空间(即数组),然后把数组依次存入 ...

  9. JAVA实现具有迭代器的线性表(顺序表)

    1,先了解下JAVA类库中的迭代器:JAVA提供了两种基本类型的迭代器,分别用两个接口来表示:Iterator<T>,ListIterator<T>.其中,Iterator&l ...

  10. java线性表之顺序表实现

    仿照arrayList写了一个简化版的线性表,主要为了用来研究arrayList在实现什么操作的情况下比较节省性能,楼主文采很差,直接上代码. import java.util.Arrays; pub ...

随机推荐

  1. MySQL InnoDB Architecture 简要介绍

    MySQL InnoDB 存储引擎整体架构图: 一.内存存储结构 1.Buffer Pool buffer pool 是主内存中的一块儿存储区域,用于存储访问的表及索引数据.这样从内存中直接访问获取使 ...

  2. qiankun vue子应用升级webpack5问题记录

    升级的方式是使用最新版本的 vue-cli 脚手架,重新创建一个新项目,然后复制 @vue/cli-xxx , vue 相关依赖最新版本到子应用项目 -> 核对babel, eslint相关配置 ...

  3. Godot 4.0 文件系统特性的总结

    关于文件系统,官方文档犹抱琵琶半遮面,有一些很独特的特性并没有集中地摆出来,导致用的时候晕头转向. 这里总结了目前我发现的Godot文件系统的一些特性. 这是专门针对导出后的,因为一些操作在编辑器里面 ...

  4. Wine运行问题 希沃-汉字卡无法显示

    在wine环境下运行希沃白板5,汉字卡无法正常显示: 这个模块是我之前参与开发的模块,过了5年还有点印象. 大概原理是获取字体库中字符的笔画路径GraphicsPath,根据里面的路径点集PathPo ...

  5. [Pytorch框架] PyTorch 中文手册

    PyTorch 中文手册 书籍介绍 这是一本开源的书籍,目标是帮助那些希望和使用PyTorch进行深度学习开发和研究的朋友快速入门. 由于本人水平有限,在写此教程的时候参考了一些网上的资料,在这里对他 ...

  6. (原创第一篇,踩坑无数得来的,对Ai自动化测试框架很有帮助)appium自动化测试时遇到不能使用element定位的在用坐标点击之后获取焦点如何输入文本

    现在开发的前端界面使用vue或者更牛逼技术,导致使用appium或者uiautomator2做自动化测试时不能识别到元素,无法使用传统的id,name或者xpath,这时我们需要使用坐标点击文本框.有 ...

  7. 【开源游戏】Legends-Of-Heroes 基于ET 7.2的双端C#(.net7 + Unity3d)多人在线英雄联盟风格的球球大作战游戏。

    Legends-Of-Heroes 一个LOL风格的球球大作战游戏,基于ET7.2,使用状态同步  Main 基于C#双端框架[ET7.2],同步到ET主干详情请看日志.(https://github ...

  8. 自建CA和公共CA有什么不同?

    据统计,全球有数百个公共CA,通常它们是按国家地区进行划分的.这类CA受大众的广泛认可和使用,也被称为公共信任的证书颁发机构.但是由于一些大型企业拥有许多站点,为了更轻松高效的管理以及考虑到维护成本, ...

  9. 2021-11-30:给定一个数组arr,当拿走某个数a的时候,其他所有的数都+a, 请返回最终所有数都拿走的最大分数。 比如: [2,3,1], 当拿走3时,获得3分,数组变成[5,4]; 当拿走5

    2021-11-30:给定一个数组arr,当拿走某个数a的时候,其他所有的数都+a, 请返回最终所有数都拿走的最大分数. 比如: [2,3,1], 当拿走3时,获得3分,数组变成[5,4]: 当拿走5 ...

  10. vue全家桶进阶之路24:Mock

    Mock 是一个 JavaScript 库,用于生成随机数据或模拟 HTTP 请求响应,用于前端开发中的单元测试.功能测试.集成测试等场景. Mock 可以生成各种类型的数据,包括字符串.数字.布尔值 ...