测试结果分析

动态数组有一个最大的弊端就是浪费内存空间,这个无法避免。
还有一个弊端就是添加删除都需要移动数组元素,最坏情况下要从头移动到尾,也就是n次,致使时间复杂度为O(n) 。
下面这个例子就解决了这个问题,通过判断索引位置,移动元素少的一端,可以至少节约一半的时间。
这个对外使用是无感的,只是内部逻辑实现不同而已。

初始化10,添加8个元素:
CircleArrayList{size=8, head=0, elementData=[1, 2, 3, 4, 5, 6, 7, 8]}
NewRealArrayList{size=8, head=0, elementData=[1, 2, 3, 4, 5, 6, 7, 8, null, null]}
删除第一个元素:
CircleArrayList{size=7, head=1, elementData=[2, 3, 4, 5, 6, 7, 8]}
NewRealArrayList{size=7, head=1, elementData=[null, 2, 3, 4, 5, 6, 7, 8, null, null]}
删除最后一个元素(此时元素有7个索引是6):
CircleArrayList{size=6, head=1, elementData=[2, 3, 4, 5, 6, 7]}
NewRealArrayList{size=6, head=1, elementData=[null, 2, 3, 4, 5, 6, 7, null, null, null]}
结尾添加一个元素:
CircleArrayList{size=7, head=1, elementData=[2, 3, 4, 5, 6, 7, 9]}
NewRealArrayList{size=7, head=1, elementData=[null, 2, 3, 4, 5, 6, 7, 9, null, null]}
删除索引为1的元素(测试删除前半的元素):
CircleArrayList{size=6, head=2, elementData=[2, 4, 5, 6, 7, 9]}
NewRealArrayList{size=6, head=2, elementData=[null, null, 2, 4, 5, 6, 7, 9, null, null]}
删除索引为4的元素(测试删除前半的元素):
CircleArrayList{size=5, head=2, elementData=[2, 4, 5, 6, 9]}
NewRealArrayList{size=5, head=2, elementData=[null, null, 2, 4, 5, 6, 9, null, null, null]}
删除索引为2的元素(测试删除中间的元素):
CircleArrayList{size=4, head=2, elementData=[2, 4, 6, 9]}
NewRealArrayList{size=4, head=2, elementData=[null, null, 2, 4, 6, 9, null, null, null, null]}
在索引为1的位置添加元素(测试添加前半的元素):
CircleArrayList{size=5, head=1, elementData=[2, 331, 4, 6, 9]}
NewRealArrayList{size=5, head=1, elementData=[null, 2, 331, 4, 6, 9, null, null, null, null]}
在索引为3的位置添加元素(测试添加后半的元素):
CircleArrayList{size=6, head=1, elementData=[2, 331, 4, 551, 6, 9]}
NewRealArrayList{size=6, head=1, elementData=[null, 2, 331, 4, 551, 6, 9, null, null, null]}
结尾添加一个元素:
CircleArrayList{size=7, head=1, elementData=[2, 331, 4, 551, 6, 9, 10]}
NewRealArrayList{size=7, head=1, elementData=[null, 2, 331, 4, 551, 6, 9, 10, null, null]}
在索引为3的位置添加元素(测试添加中间的元素):
CircleArrayList{size=8, head=1, elementData=[2, 331, 4, 550, 551, 6, 9, 10]}
NewRealArrayList{size=8, head=1, elementData=[null, 2, 331, 4, 550, 551, 6, 9, 10, null]}
在索引为5的位置添加两个元素(测试绕环):
CircleArrayList{size=10, head=1, elementData=[2, 331, 4, 550, 551, 552, 553, 6, 9, 10]}
NewRealArrayList{size=10, head=1, elementData=[10, 2, 331, 4, 550, 551, 552, 553, 6, 9]}
删除刚才添加的两个元素(测试删除对象):
CircleArrayList{size=8, head=1, elementData=[2, 331, 4, 550, 551, 6, 9, 10]}
NewRealArrayList{size=8, head=1, elementData=[null, 2, 331, 4, 550, 551, 6, 9, 10, null]}
在索引为2的位置添加两个元素(测试前绕环):
CircleArrayList{size=10, head=-1, elementData=[2, 331, 332, 333, 4, 550, 551, 6, 9, 10]}
NewRealArrayList{size=10, head=-1, elementData=[331, 332, 333, 4, 550, 551, 6, 9, 10, 2]}
在索引为5的位置添加一个元素(测试扩容):
CircleArrayList{size=11, head=0, elementData=[2, 331, 332, 333, 4, 441, 550, 551, 6, 9, 10]}
NewRealArrayList{size=11, head=0, elementData=[2, 331, 332, 333, 4, 441, 550, 551, 6, 9, 10, null, null, null, null]}

源代码

package datastruct.linearlist;import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;/*** 循环数组* 核心在于索引* 提升效率* 前半添加前半删除扩容缩容处理head*/
public class HtqCircleArrayList<E> {private int head;private int size;private Object[] elementData;private int DEFAULT_CAPACITY = 10;private Object[] EMPTY_ELEMENTDATA = {};private int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;public HtqCircleArrayList() {elementData = EMPTY_ELEMENTDATA;}public HtqCircleArrayList(int initCapacity) {if (initCapacity<0){throw new IllegalArgumentException();}else if (initCapacity ==0){elementData = EMPTY_ELEMENTDATA;}else {elementData = new Object[initCapacity];}}private int realIndex(int index){return (index+head>=elementData.length)?(index+head-elementData.length):(index+head<0)?index+head+elementData.length:index+head;}//error no checkpublic void trimToSize(){if (size>=elementData.length) return;if (size==0){elementData = EMPTY_ELEMENTDATA;return;}Object[] objects = new Object[size];for (int i=0;i<size;i++){objects[i] = elementData[realIndex(i)];elementData[realIndex(i)] = null;}elementData = objects;}public int size(){return size;}public boolean isEmpty(){return size==0;}public boolean contins(Object o){return indexOf(o)!=-1;}//error 0->oprivate int indexOf(Object o) {for (int i=0;i<size;i++){if (Objects.equals(elementData[realIndex(i)],o)){return i;}}return -1;}private int lastIndexOf(Object o) {for (int i=size-1;i>=0;i--){if (Objects.equals(elementData[realIndex(i)],0)){return i;}}return -1;}public void clear(){for (int i=0;i<size;i++){elementData[realIndex(i)] = null;}saveCapacity(size);size = 0;}public Object[] toArray(){Object[] objects = new Object[size];for (int i=0;i<size;i++){objects[i] = elementData[realIndex(i)];}return objects;}public <T> T[] toArray(T[] a){if(a.length<size){a = (T[])Array.newInstance(a.getClass().getComponentType(),size);}Object[] o = a;for (int i=0;i<size;i++){o[i] = elementData[realIndex(i)];}if (a.length<size){a[size] = null;}return a;}//no Comparetorpublic void sort(Comparator<? super  E> comparator){trimToSize();Arrays.sort((E[])elementData,0,size,comparator);}public void add(E e){ensureCapacityInternal(size+1);elementData[realIndex(size++)] = e;}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculate(minCapacity));}private void ensureExplicitCapacity(int minCapacity) {if (minCapacity>elementData.length){grow(minCapacity);}}//no deal headprivate void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + oldCapacity>>1;if (newCapacity<minCapacity){newCapacity = minCapacity;}if (newCapacity>MAX_ARRAY_SIZE){newCapacity = (minCapacity>MAX_ARRAY_SIZE)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;}Object[] objects = new Object[newCapacity];for (int i=0;i<size;i++){objects[i] = elementData[realIndex(i)];}elementData = objects;head = 0;}private int calculate(int minCapacity) {if (elementData == EMPTY_ELEMENTDATA){minCapacity = Math.max(minCapacity,DEFAULT_CAPACITY);}return minCapacity;}//error no ensureCapacityInternal()//i>=index no deal indexpublic void add(int index,E e){rangeCheckForAdd(index);ensureCapacityInternal(size+1);if (index<(size>>1)){for (int i=0;i<index;i++){elementData[realIndex(i-1)] = elementData[realIndex(i)];}head = head-1;}else {for (int i=size-1;i>=index;i--){elementData[realIndex(i+1)] = elementData[realIndex(i)];}}elementData[realIndex(index)] = e;size++;}@Override public String toString() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("CircleArrayList{size=").append(size).append(", head=").append(head).append(", elementData=[");for (int i=0;i<size;i++){if (i==0){stringBuilder.append(elementData(i));continue;}stringBuilder.append(", "+elementData(i));}stringBuilder.append("]}");return stringBuilder.toString();}public String toRealString() {return "NewRealArrayList{" +"size=" + size +", head=" + head +", elementData=" + Arrays.toString(elementData) +'}';}private void rangeCheckForAdd(int index) {if (index<0||index>size)throw new IndexOutOfBoundsException();}private void rangeCheck(int index) {if (index<0||index>=size)throw new IndexOutOfBoundsException();}public E remove(int index){rangeCheck(index);E e = elementData(index);if (index<(size>>1)){for (int i=index-1;i>=0;i--){elementData[realIndex(i+1)] = elementData[realIndex(i)];}elementData[head] = null;head = head+1;}else {for (int i=index+1;i<size;i++){elementData[realIndex(i-1)] = elementData[realIndex(i)];}elementData[realIndex(size-1)] = null;}size--;saveCapacity(size);return e;}//error no deal headprivate void saveCapacity(int size) {if (size<(elementData.length>>1)){Object[] objects = new Object[elementData.length>>1];for (int i=0;i<size;i++){objects[i] = elementData[realIndex(i)];elementData[realIndex(i)] = null;}elementData = objects;head=0;}}private E elementData(int index){return (E)elementData[realIndex(index)];}public E remove(E e){int i = indexOf(e);return remove(i);}public E set(int index,E e){E oe = elementData(index);elementData[realIndex(index)] = e;return oe;}public E get(int index){return elementData(index);}
}

测试类

package datastructure.linearlist;public class CircleArrayListTest {public static void main(String[] args) {HtqCircleArrayList circleArrayList = new HtqCircleArrayList(10);System.out.println("初始化10,添加8个元素:");circleArrayList.add(1);circleArrayList.add(2);circleArrayList.add(3);circleArrayList.add(4);circleArrayList.add(5);circleArrayList.add(6);circleArrayList.add(7);circleArrayList.add(8);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除第一个元素:");circleArrayList.remove(0);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除最后一个元素(此时元素有7个索引是6):");circleArrayList.remove(6);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("结尾添加一个元素:");circleArrayList.add(9);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除索引为1的元素(测试删除前半的元素):");circleArrayList.remove(1);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除索引为4的元素(测试删除前半的元素):");circleArrayList.remove(4);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除索引为2的元素(测试删除中间的元素):");circleArrayList.remove(2);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为1的位置添加元素(测试添加前半的元素):");circleArrayList.add(1,331);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为3的位置添加元素(测试添加后半的元素):");circleArrayList.add(3,551);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("结尾添加一个元素:");circleArrayList.add(10);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为3的位置添加元素(测试添加中间的元素):");circleArrayList.add(3,550);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为5的位置添加两个元素(测试绕环):");circleArrayList.add(5,553);circleArrayList.add(5,552);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("删除刚才添加的两个元素(测试删除对象):");circleArrayList.remove((Object)553);circleArrayList.remove((Object)552);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为2的位置添加两个元素(测试前绕环):");circleArrayList.add(2,333);circleArrayList.add(2,332);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());System.out.println("在索引为5的位置添加一个元素(测试扩容):");circleArrayList.add(5,441);System.out.println(circleArrayList);System.out.println(circleArrayList.toRealString());}
}

动态循环数组(ArrayList优化)相关推荐

  1. android动态扩容数组,ArrayList 扩容 Android Java 真的不一样

    以前学java基础的时候 看过ArrayList的扩容机制 实现原理是下面这样 当时做的笔记 ArrayList扩容机制 在jdk1.7前是 *3/2+1 在jdk1.7开始就是 old+(old&g ...

  2. 动态数组ArrayList c# 1613536290

    动态数组ArrayList c# 1613536290 导入命名空间 using System.Collections; 实例化对象 空对象 ArrayList 对象 = new ArrayList( ...

  3. java二维数组添加元素_Java二维数组与动态数组ArrayList类详解

    java二维数组 java 语言中提供的数组是用来存储固定大小的同类型元素. 1.二维数组初始化和声明 数组变量的声明,和创建数组可以用一条语句完成,如下所示: int a[][] = new int ...

  4. 力扣【下一个更大元素】leetcode-503.下一个更大元素 Ⅱ:单调栈解法+循环数组解法

    题目: 思路与解法: 1.如果是暴力法,只需要遍历就可以了,但是那样的话时间复杂度就是O(N^2); 2.可以把这几个数字,抽象成为高度不一样的柱子: 3.寻找的过程,就是从当前柱子去看,被后面的哪一 ...

  5. 约瑟夫问题的学习(基于循环链表)以及基于循环数组

    这是17世纪法国数学家加斯帕在<数目中的游戏问题>讲的一个问题:15个教徒和15个非教徒在海上遇险,必须将一般的人投入海中,其他的人才能幸免于难.与实现各一个办法:30个人围成一个圈,从第 ...

  6. java 循环map 优雅写法_Java for循环Map集合优化实现解析

    这篇文章主要介绍了java for循环map集合优化实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在<for循环实战性能优化> ...

  7. for循环之性能优化

    前言 for循环是开发时常用的语法之一,比如对数组,集合的遍历等,但是如果使用不好也会出现很多新能损耗的问题,今天就来讲解一下for循环的常用性能优化问题. 嵌套循环 嵌套循环是有俩层或者俩层以上的循 ...

  8. 《恋上数据结构第1季》动态扩容数组原理及实现

    动态扩容数组 什么是数据结构? 线性表 数组(Array) 动态数组(Dynamic Array) 动态数组接口设计 清除所有元素 - clear() 添加元素 - add(E element).ad ...

  9. C/C++动态开辟数组【C++:new/delete(推荐):int *arr = new int[m];】【C++:vector】【C:malloc() free()】

    一.C++的new/delete(推荐) 1.动态开辟一维数组 #include<iostream> #include<stdio.h>using namespace std; ...

最新文章

  1. ScaleYViewPager
  2. BERT+CRF的损失函数的研究
  3. module 'torch.jit' has no attribute 'unused'
  4. MySQL 5.7 安装指南
  5. 硬刚一周,3W字总结,一年的经验告诉你如何准备校招,拿大厂offer
  6. 与 SENet 互补提升,华为提出自注意力新机制:Weight Excitation
  7. 小学计算机说课稿,小学信息技术说课稿《新建文件夹》
  8. html的带分页的表格写法,Html表格分页
  9. CUDA零拷贝内存(zerocopy memory)
  10. Timeline的Animation Track详解
  11. excel查找空值快捷键_『EXCEL定位条件快捷键』excel定位空值填充
  12. 郁金香商业辅助教程 2016 笔记 1~5
  13. VP9编码:迄今的尝试
  14. 关于app的几个核心功能的设计想法
  15. 美国3D理发师可剪出球星脸发型
  16. Excel按照固定行数拆分为多个文件
  17. Opencv__模板匹配(上)
  18. Palo, Palo
  19. centos挂载u盘只读_解决CentOS自动挂载U盘/SD Card被识别为只读文件系统
  20. Vulkan的基本概念:如何使用Vulkan绘制三角形?

热门文章

  1. 开车的人和不开车的人思维有什么区别?
  2. 按键精灵大漠插件使用基础练习入门代码
  3. ultraedit编译java_在UltraEdit中编译和运行Java程序
  4. 北京市中 高英语听说计算机考,北京市教育委员会关于听力及言语障碍考生参加2019年中考英语听说计算机考试有关事项的通知...
  5. vue 数字动画递增_数字滚动动画效果 vue组件化
  6. matlab获取图像某点RGB值、灰度值的方法
  7. Java简单项目 水果摊
  8. 如何更高好地管理待办事项?
  9. java,NIO,UDP协议网络通信DEMO
  10. Python 文件 tell() 方法