您的位置 首页 java

手写java数据结构(动态数组)

我们都知道java提供的数组一旦初始化后,长度是固定的无法进行扩容。所以今天我们对数组进行封装重新编写一个更强大的数组(也可以看做简单版ArrayList)

//定义一个数组类
public class Array<E> {
	 //默认数组
 private E [] data;
	//数组元素个数
 private int size;
 //初始化指定容量的 构造函数 
 public Array(int initCapacity){
 //java不支持直接new 泛型类型的数组所以需要进行类型转换
 data = (E[]) new Object[initCapacity];
 size = 0;
 }

 // 无参构造函数默认容量10
 public Array(){
 this(10);
 }
 //获取数组元素个数
 public int getSize(){
 return size;
 }
 //获取数组容量
 public int getCapacity(){
 return data.length;
 }
 //数组是否为空
 public boolean isEmpty(){
 return size == 0;
 }
//向指定索引位置添加元素
 public void add(int index,E e){
 if(index < 0 || index > size){
 //index < size是为了防止数组中间出现空隙,从而保证数组数据紧密连续的在一起
 throw new IllegalArgumentException("array is error");
 }
 if(size == data.length){
 //插入数据时如果当前数组已满,需要对数组进行扩容,扩容现有数组的两倍而jdk是1.5倍
 resize(2*data.length);
 }
 //在指定索引位置插入元素时,要将该位置及其后面的元素往后移动一个位置
 for(int i = size - 1; i >= index; i--){
 data[i + 1] = data[i];
 }
 data[index] = e;
 size++;
 }
 //向数组末尾添加元素
 public void addLast(E e){
 add(size,e);
 }
 //向数组头部添加元素
 public void addFirst(E e){
 add(0,e);
 }
 //数组扩容,新建一个容量为原数组两倍的新数组,然后将原数组元素添加到新数组,
//然后将新数组引用赋值给原数组
 private void resize(int newCapacity){
 E[] newData = (E[]) new Object[newCapacity];
 for(int i = 0; i < size;i++){
 newData[i] = data[i];
 data = newData;
 }
 }

 //获取指定索引位置元素
 public E get(int index){
 if(index < 0 || index > size){
 throw new IllegalArgumentException("index is illegal");
 }
 return data[index];
 }
 //修改元素
 public void set(int index,E e){
 if(index < 0 || index > size){
 throw new IllegalArgumentException("index is illegal");
 }
 data[index] = e;
 }
 //数组是否包含某个元素
 public boolean contains(E e){
 for(int i = 0; i < size; i++){
 if(data[i].equals(e)){
 return true;
 }
 }
 return false;
 }
 //查找数组元素e所在的索引,如果不存在则返回-1
 public int find(E e){
 for(int i = 0; i < size; i++){
 if(data[i].equals(e)){
 return i;
 }
 }
 return -1;
 }
 //删除指定索引位置的元素,并返回删除的元素
 public E remove(int index){

 if(index < 0 || index > size){
 throw new IllegalArgumentException("index is illegal");
 }
 E ret = data[index];
 //删除指定位置索引同样需要移动其他元素
 for(int i = index + 1; i < size; i++){
 data[i-1] = data[i];
 }
 //如果元素是引用类型数据,为避免一直占据内存空间,需要将其赋为null
 data[size] = null;
 size--;
 //缩容
 if(size == data.length/4 && data.length /2 !=0){
 resize(data.length/2);
 }
 return ret;
 }
 //从数组中删除第一个元素
 public E removeFirst(){
 return remove(0);
 }
 //从数组中删除最后一个元素
 public E removeLast(){
 return remove(size - 1);
 }
 //从数组删除某个元素
 public void removeElement(E e){
 int res = find(e);
 if(res != -1){
 remove(res);
 }
 }
//获取最后一个元素
 public E getLast(){
 return get(size-1);
 }
 @Override
 public String toString(){
 StringBuilder sb = new StringBuilder();
 sb.append(String.format("Array:size = %d,capacity = %d\n",size,data.length));
 sb.append("[");
 for(int i = 0; i < size; i++){
 sb.append(data[i]);
 if(i != size - 1){
 sb.append(",");
 }
 }
 sb.append("]");
 return sb.toString();
 }

}
 

由此我们可以判断:通过索引进行的查找操作时间复杂度为O(1)

addLast()理想情况下为O(1),如果触发扩容则为O(n)。

因此我们在使用ArrayList 集合的时候如果数据量较大而且数据数量已知的时候,

初始化时指定容量大小可以获得较大的性能提升。

下期我们根据封装好的数组实现“ 栈 ” 这种数据结构

———本文源于日常学习笔记记录,如有错误欢迎批评指正

文章来源:智云一二三科技

文章标题:手写java数据结构(动态数组)

文章地址:https://www.zhihuclub.com/187666.shtml

关于作者: 智云科技

热门文章

网站地图