java基础---数组的数据结构

本文深入探讨了在Java中自定义数组的实现方法,包括数组的定义、基本操作如增删改查,以及如何使用泛型增强数组的通用性。同时,文章还介绍了动态数组的实现,讨论了在增加和删除元素时如何处理数组空间的动态调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

在学习JAVA的基础的时候,我们只是简单的学习了数组的定义和怎么访问数组的元素,而且JAVA内部也替我们实现了数组的基本操作,我们没有过多的去考虑数组底层实现,所以本篇文章主要讲有关于数据结构里面的数组的基本操作,不会利用JAVA数组本身实现的操作,我们自己实现这些内部的底层。

数组的定义

数组是相同类型的 、用一个标识符名称来封装到一起的一个对象序列或基本类型的数据序列;也就是说数组充当一个容器,专门存储同种类型的数据或对象。

数组的使用

声明一个数组:int [] a = new int[10]或者int a[] = new int[10];

通过下标使用: a[0]—>获取数组的第一个元素

数组的基本操作

  1. 数组的定义

    public class MyArray {
    	private int[] data;
    	private int size;
    	//有参构造函数,根据传入参数构造数组的容量
    	public MyArray(int cap){
    		this.data = new int[cap];
    		this.size = 0;
    	}
    	//无参构造函数,默认数组的容量为10
    	public MyArray(){
    		this(10);
    	}
    }
    
  2. 获取数组的基本数据

    	//获取数组的容量
    	public int getCapacity(){
    		return this.data.length;
    	}
    	//获取数组中元素的个数
    	public int getSize(){
    		return this.size;
    	}
    	//判断数组是否为空
    	public boolean isEmpty(){
    		return this.size==0;
        }
    
  3. 数组的增删改

    /**
    	 * 往数组中添加元素
    	 * @param index:索引
    	 * @param e:添加的元素
    	 */
    	public void add(int index, int e){
    		if(this.size == this.data.length){
    			throw new IllegalArgumentException("添加失败,数组已经满了!");
    		}
    		if(index <0 || index >this.size){
    			throw new IllegalArgumentException("添加失败,插入的索引出错!");
    		}
    		for(int i = this.size; i > index; i--){
    			data[i] = data[i-1];
    		}
    		this.data[index]=e;
    		this.size++;
    	}
    	//往数组首位置添加元素
    	public void addFirst(int e){
    		this.add(0, e);
    	}
    	//在所有数组元素后添加元素
    	public void addLast(int e){
    		this.add(this.size, e);
    	}
    	//获取index位置的元素
    	public int getElement(int index){
    		if(index < 0 || index >=this.size){
    			throw new IllegalArgumentException("getElement-->index出错!");
    		}
    		return this.data[index];
    	}
    	//修改index位置的元素
    	public void setElement(int index, int e){
    		if(index < 0 || index >=this.size){
    			throw new IllegalArgumentException("setElement-->index出错!");
    		}
    		this.data[index]=e;
    	}
    	//查找元素e是否在数组中,返回索引
    	public int find(int e){
    		for(int i =0 ; i< this.size; i++){
    			if(this.data[i] == e)return i;
    		}
    		return -1;
    	}
    	//查看数组是否包含该元素
    	public boolean contains(int e){
    		return this.find(e) != -1;
    	}
    	//删除index元素,并返回删除元素
    	public int remove(int index){
    		if(index <0 || index >=this.size){
    			throw new IllegalArgumentException("删除失败-->index出错");
    		}
    		int res = this.data[index];
    		for(int i = index; i<this.size; i++){
    			this.data[i]=this.data[i+1];
    		}
    		this.size--;
    		return res;
    	}
    	//删除数组第一个元素
    	public int removeFirst(){
    		return this.remove(0);
    	}
    	//删除数组最后一个元素
    	public int removeLast(){
    		return this.remove(this.size-1);
    	}
    
  4. 复写toString方法和测试

    @Override
    	public String toString() {
    		StringBuffer sb = new StringBuffer();
    		sb.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
            sb.append('[');
            for(int i = 0 ; i < this.size ; i ++){
                sb.append(this.data[i]);
                if(i != this.size - 1)
                    sb.append(", ");
            }
            sb.append(']');
            return sb.toString();
     
    	}
    	public static void main(String[] args) {
    		MyArray arr = new MyArray(20);
            for(int i = 0 ; i < 20 ; i ++)
                arr.addLast(i);
            System.out.println(arr);
    
            arr.add(1, 100);
            System.out.println(arr);
    
            arr.addFirst(-1);
            System.out.println(arr);
           
            System.out.println( arr.getElement(4));
            
            arr.setElement(4,50);
            System.out.println(arr);
            
            System.out.println(arr.find(50));
            System.out.println(arr.find(150));
            
            System.out.println(arr.contains(50));
            System.out.println(arr.contains(150));
            
            System.out.println(arr.remove(13));
            System.out.println(arr);
            
            System.out.println(arr.removeFirst());
            System.out.println(arr);
            
            System.out.println(arr.removeLast());
            System.out.println(arr);
    	}
    
  5. 使用泛型

    上述数组的数据结构明显只能存储int类型的属性,并只能对int类型的数据进行操作,没有通用性可言,现在使用泛型来解决我们的问题,与上述的实现有以下的区别。

    • 首先要声明泛型才能使用泛型
    • 增删查改的元素都是泛型
    • 有参构造函数需要进行强制类型转换
    public class ArrayGeneric<E> {
    		private E[] data;
    		private int size;
    		//有参构造函数,根据传入参数构造数组的容量
    		public ArrayGeneric(int cap){
    			this.data = (E[]) new Object[cap];
    			this.size = 0;
    		}
    		//无参构造函数,默认数组的容量为10
    		public ArrayGeneric(){
    			this(10);
    		}
    		//获取数组的容量
    		public int getCapacity(){
    			return this.data.length;
    		}
    		//获取数组中元素的个数
    		public int getSize(){
    			return this.size;
    		}
    		//判断数组是否为空
    		public boolean isEmpty(){
    			return this.size==0;
    		}
    		/**
    		 * 往数组中添加元素
    		 * @param index:索引
    		 * @param e:添加的元素
    		 */
    		public void add(int index, E e){
    			if(this.size == this.data.length){
    				throw new IllegalArgumentException("添加失败,数组已经满了!");
    			}
    			if(index <0 || index >this.size){
    				throw new IllegalArgumentException("添加失败,插入的索引出错!");
    			}
    			
    			for(int i = this.size; i > index; i--){
    				data[i] = data[i-1];
    			}
    			this.data[index]=e;
    			this.size++;
    		}
    		//往数组首位置添加元素
    		public void addFirst(E e){
    			this.add(0, e);
    		}
    		//在所有数组元素后添加元素
    		public void addLast(E e){
    			this.add(this.size, e);
    		}
    		//获取index位置的元素
    		public E getElement(int index){
    			if(index < 0 || index >=this.size){
    				throw new IllegalArgumentException("getElement-->index出错!");
    			}
    			return this.data[index];
    		}
    		//修改index位置的元素
    		public void setElement(int index, E e){
    			if(index < 0 || index >=this.size){
    				throw new IllegalArgumentException("setElement-->index出错!");
    			}
    			this.data[index]=e;
    		}
    		//查找元素e是否在数组中,返回索引
    		public int find(E e){
    			for(int i =0 ; i< this.size; i++){
    				if(this.data[i] == e)return i;
    			}
    			return -1;
    		}
    		//查看数组是否包含该元素
    		public boolean contains(E e){
    			return this.find(e) != -1;
    		}
    		//删除index元素,并返回删除元素
    		public E remove(int index){
    			if(index <0 || index >=this.size){
    				throw new IllegalArgumentException("删除失败-->index出错");
    			}
    			E res = this.data[index];
    			for(int i = index; i<this.size; i++){
    				this.data[i]=this.data[i+1];
    			}
    			this.size--;
    			return res;
    		}
    		//删除数组第一个元素
    		public E removeFirst(){
    			return this.remove(0);
    		}
    		//删除数组最后一个元素
    		public E removeLast(){
    			return this.remove(this.size-1);
    		}
    		// 将数组空间的容量变成newCap大小
    	    private void resize(int newCap){
    	        E[] newData = (E[])new Object[newCap];
    	        for(int i = 0 ; i < size ; i ++)
    	            newData[i] = this.data[i];
    	        this.data = newData;
    	    }
    
    		@Override
    		public String toString() {
    			StringBuffer sb = new StringBuffer();
    			sb.append(String.format("Array: size = %d , cap = %d\n", size, data.length));
    	        sb.append('[');
    	        for(int i = 0 ; i < this.size ; i ++){
    	            sb.append(this.data[i]);
    	            if(i != this.size - 1)
    	                sb.append(", ");
    	        }
    	        sb.append(']');
    	        return sb.toString();
    	 
    		}
    }
    

    使用泛型的数组存储的对象的实例

    public class Student {
    	private String name;
    	private int age;
    	
    	public Student(String name, int age){
    		this.name=name;
    		this.age=age;
    	}
    	@Override
    	public String toString() {
    		return String.format("Student(name:%s,age:%d)", this.name,this.age);
    	}
    	public static void main(String[] args) {
    		ArrayGeneric<Student> arr = new ArrayGeneric<Student>();
    	        arr.addLast(new Student("Tan", 100));
    	        arr.addLast(new Student("Ldx", 66));
    	        arr.addLast(new Student("AAA", 88));
    	        System.out.println(arr);
    	}
    }
    
  6. 动态数组的实现

    • 在增加元素的时候,需要判断是否要开辟空间
    • 在删除元素的时候,如果删除的元素过多,导致内存空间利用率低,而选择重新分配空间(进行缩减空间)
    • 除了增加和删除的操作需要做出相应的修改,其他的操作不需要修改(仅上部分代码)
    		/**
    		 * 往数组中添加元素
    		 * @param index:索引
    		 * @param e:添加的元素
    		 */
    		public void add(int index, E e){
    			if(index <0 || index >this.size){
    				throw new IllegalArgumentException("添加失败,插入的索引出错!");
    			}
    			//扩容
    			if(this.size == this.data.length){
    				this.resize(this.getCapacity()*2);
    			}
    		
    			for(int i = this.size; i > index; i--){
    				data[i] = data[i-1];
    			}
    			this.data[index]=e;
    			this.size++;
    		}
    		//删除index元素,并返回删除元素
    		public E remove(int index){
    			if(index <0 || index >=this.size){
    				throw new IllegalArgumentException("删除失败-->index出错");
    			}
    			E res = this.data[index];
    			for(int i = index; i<this.size-1; i++){
    				this.data[i]=this.data[i+1];
    			}
    			this.size--;
    			this.data[size]=null;
    			if(this.size <= this.data.length/2)this.resize(this.data.length/2);
    			return res;
    		}
    		// 将数组空间的容量变成newCap大小
    		private void resize(int newCap){
    			E[] newData = (E[])new Object[newCap];
    			for(int i = 0 ; i < size ; i ++)
    		        newData[i] = this.data[i];
    		    this.data = newData;
    		}
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值