java arraylist 结构_Java自定义ArrayList(顺序存储结构)和性能分析

1. 自定义ArrayList

首先我们先看一个案例:

假如一个球场的教练,安排球员(5个)上场

模拟数据存储的案例,模拟上场球员的球衣号码的存储。

(1)初始容量为5的线性列表,准备用来存储场上的5个球衣号码:[11,22,33,44,55]

(2)查询指定位置的球员球衣号码是多少,查询索引位置为2的球衣号码如:33;

(3)根据球衣号码查询该球员在场上的索引位置,44在球衣号码的球员在场上的索引位置是3

(4)替换球场上索引位置为2的球员,替换之后该位置的球衣编号为,333

(5)替换球衣号码为22的球员,替换之后为222;

(6)把场上索引位置为2的球员罚下场

(7)按照球员在场上的位置,打印出球衣的号码,打印风格[11,22,33,44,55]

其实一开始想通过这个案例,引出ArrayList,但是显得有点啰嗦,其实说到底,上面对球员的操作不过就是对数组的操作,在之前介绍数组时候,已经讲到了数组有关的简单操作,如数组元素的打印,拷贝,替换。

但是数组毕竟是一种简单的数据存储结构,存储的数据长度是固定的。因此,我们可以基于数组封装一个数据集合,更灵活的存储数据。

1.1 自定义要实现的方法(接口)

public void addEle(Object ele); // 添加元素 public Object findEleByIndex(int index); // 查询指定索引位置的元素 public int findIndexByEle(Object ele);// 查询指定元素的索引位置 public void replaceEleByIndex(Object newEle, int index);// 替换指定索引位置的元素 public void replaceEleByEle(Object ele, int newEle); // 替换指定的元素 public void deleteEleByIndex(int index); // 删除指定索引位置的元素 public void deleteEleByEle(Object ele); // 删除指定元素 public int getSize(); // 返回数组元素的个数 public boolean isEmpty(); // 判断数组中的元素个数是否为零 public void clear(); //清空数组集合 public String toString() // 覆盖父类(Object)方法,按格式打印数组

1.2 自定义ArrayList类

class MyArrayList { private Object[] num = null; private int size = 0; private final static int DEFAULT_INIT_CAPACITY = 10;// 模型长度 public MyArrayList() { this(DEFAULT_INIT_CAPACITY); } public MyArrayList(int capacity) { if (capacity < 0) { throw new IllegalArgumentException("容量不能为负数"); } num = new Object[capacity]; } // 添加元素 public void addEle(Object ele) { // 判断是否需要扩容(性能非常低) // (1) 创建一个新数组 // (2) 把旧数组的元素拷贝到新的数组中 if (size == num.length) { Object[] newNum = Arrays.copyOf(num, num.length * 2 + 1); num = newNum; } num[size] = ele; size++; } // 查询指定索引位置的元素 public Object findEleByIndex(int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("索引越界"); } return num[index]; } // 查询指定元素的索引位置 public int findIndexByEle(Object ele) { for (int i = 0; i < size; i++) { if (ele.equals(num[i])) { return i; } } return -1; } // 替换指定索引位置的元素 public void replaceEleByIndex(Object newEle, int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("索引越界"); } num[index] = newEle; } // 替换指定的元素 public void replaceEleByEle(Object ele, int newEle) { // 先查询该元素的索引位置 int index = findIndexByEle(ele); if (index < 0) { throw new IllegalArgumentException("该元素不存在"); } replaceEleByIndex(newEle, index); } // 删除指定索引位置的元素 public void deleteEleByIndex(int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("索引越界"); } for (int i = 0; i < size - 1 - index; i++) { num[index + i] = num[index + i + 1]; } num[size - 1] = null; size--; } // 删除指定元素 public void deleteEleByEle(Object ele) { int index = findIndexByEle(ele); if (index == -1) { throw new IllegalArgumentException("所删除的元素不存在"); } deleteEleByIndex(index); } // 返回数组元素的个数 public int getSize() { return size; } // 判断数组中的元素个数是否为零 public boolean isEmpty() { return size == 0; } //清空数组 public void clear() { this.num = new Object[DEFAULT_INIT_CAPACITY]; size = 0; } // 按格式打印数组 public String toString() { if (num == null) { System.out.println("null"); } StringBuilder sb = new StringBuilder("["); for (int i = 0; i < size; i++) { sb = sb.append(num[i]); if (i != size - 1) { sb = sb.append(","); } } sb = sb.append(']'); return sb.toString(); } }

1.2 定义测试类

public class ArrayListDemo { public static void main(String[] args) { MyArrayList myArrayList = new MyArrayList(); myArrayList.addEle(11); myArrayList.addEle(22); myArrayList.addEle("33"); myArrayList.addEle("44"); myArrayList.addEle("55"); myArrayList.addEle("66"); // 这里就开始扩容了 System.out.println(myArrayList.findIndexByEle("55")); System.out.println(myArrayList); } }

输出:

4 [11,22,33,44,55,66]

2. ArrayList性能分析

(1)保存操作

如果将新的数据保存在最后一个位置,至少需要操作1次;

如果将新加的数据保存在数组第一个位置,假设存在N个元素,此时需要操作N次(后面的元素往后移动N-1次,添加操作再算一次,一共操作N次);

(2)删除操作

如果删除最后一个元素,操作1次;

如果删除第一个元素,操作N次;

平均 (N+1) / 2

(3)修改操作

操作一次

(4)查询操作

如果根据索引查询元素,操作1次;

如果根据元素查询索引:此时使用线性搜索,平均(N+1) / 2

总结

基于数组的结构做查询和修改是非常快的,但是做保存和删除操作就比较慢了。

如何保证保存和删除操作的性能?那就要用到链表数据结构了。

本文地址:https://blog.csdn.net/weixin_43519707/article/details/107885192

希望与广大网友互动??

点此进行留言吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的数组是一种线性数据结构,它由相同类型的元素组成并按照顺序存储在内存中。Java中的数组可以使用new关键字动态地创建,并且长度是固定的,一旦创建后就不能再改变它的大小。 Java中的ArrayList是一个动态数组,它可以自动扩容以适应元素的添加和删除。ArrayList实际上是基于数组实现的,它内部维护了一个Object类型的数组来存储元素。当ArrayList的容量不足时,它会根据一定的策略自动扩容数组的大小,以容纳更多的元素。 ArrayList的实现原理主要包括以下几个方面: 1. 初始容量和扩容因子:当创建一个ArrayList时,可以指定一个初始容量和一个扩容因子。初始容量指定了ArrayList内部数组的初始大小,扩容因子指定了数组增长的比例。默认情况下,初始容量为10,扩容因子为1.5。 2. 自动扩容:当ArrayList内部数组的容量不足时,它会自动扩容。具体实现是创建一个新的数组,将原数组中的元素复制到新数组中,并将新元素添加到新数组中。 3. 随机访问:由于ArrayList是基于数组实现的,因此它支持随机访问。可以通过索引来快速访问元素,时间复杂度为O(1)。 4. 插入和删除:在ArrayList中插入和删除元素的时间复杂度取决于操作的位置。如果在末尾插入或删除元素,时间复杂度为O(1),否则需要将后面的元素都向后移动,时间复杂度为O(n)。 总之,ArrayListJava中常用的动态数组,它的实现基于数组,并且支持随机访问、自动扩容等特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值