静态数组:
平时我们使用的数组静态数组,数组一旦创建,数组的长度就不能改变;但在实际应用有很大的局限性,即在应用时往往不能确切的知道需要创建多大的数组,若创建的数组长度太大,则会造成资源浪费,若长度太小则不够用的。
动态数组:
动态数组是在静态数组的基础上对静态数组进行二次封装,动态数组在使用中可以根据数组中的元素的个数动态的扩容数组的长度,动态数组也提供了静态数组的插入、删除、查找、修改等方法。动态数组也提供了在数组制定的位置插入或删除数组,在指定的位置删除数组时会把删除元素后面的元素一次往前移动,填补删除元素的位置,保证了数组中每个元素都紧紧相邻的特性。
/**
*
*
* 自定义动态数组:
* 定义类动态Array,对原生的数据进行二次封装,使之可以动态的添加和删除元素时不改变数组的特性(即数组中的元素都是紧紧相邻de)
*
* 给动态数组使用泛型<E>,扩展动态数组可以保存任意类型的元素
*
* @author
*
*/
public class Array<E> {
private E[] data;//定义一个int类型的数组,以int类型的数组为例对原生的数组进行二次封装
private int size;//表示数据实际元素的个数,不是数组的容量(长度)length
/**
* 根据传入创建数组的容量来实例化数组
* @param capacity
*/
public Array(int capacity){
/**
* 因为泛型在运行期会被檫除,所以要注意:
* 注意使用泛型创建数组时,不能直接来 new E[]来创建,因为E并不是具体的类型;
* 可以通过new Object[],再把Object[]强转为E[]类型,即:
* data = (E[])new Object[capacity]
*/
data = (E[])new Object[capacity];//根据传入的数组的长度capacity,实例化数组data
size = 0;
}
/**
* 默认构造方法,设置数组的默认长度为10
*/
public Array(){
this(10);//设置默认数组的长度为10,this(10)表示调用当前数组的构造方法
}
/**
* 获取数组的容量
* @return
*/
public int getCapacity(){
return data.length;
}
/**
* 返回数组中元素的个数
* @return
*/
public int getSize(){
return size;
}
/**
* 判断数组为空
* @return
*/
public boolean isEmpty(){
return size == 0;
}
/**
* 向数组最后一个位置添加元素
* @param e
*/
public void addLast(E e){
/**
*
//向数组添加元素之前要判断数组是否已经满了
if(size == data.length){
throw new IllegalArgumentException("AddLast filed,Array is full");//抛出异常:末尾元素添加失败,数组已经满了
}
data[size] = e;//把e添加到末尾,数组下标从零开始,数组有size个元素,则最后一个元素的index是size-1,
//所以向数组末尾添加元素时新添加元素的index就是size
size++;//数组个数加一
*/
//向数组末尾添加元素,相当于在指定位置index=size的位置添加元素
add(size,e);
}
/**
* 向数组第一个位置添加元素
* @param e
*/
public void addFirst(E e){
//向数组首位添加元素,相当于在指定位置index=0的位置添加元素
add(0,e);
}
/**
* 向数组指定的位置添加元素
* @param index 元添加的位置素
* @param e 要添加的元素
*/
public void add(int index,E e){
/**
* 判断输入的index是否合法,index不能小于0,为了保证数组中元素的紧密连接,index不能大于size
*/
if(index < 0 || index>size){
throw new IllegalArgumentException("Add filed,Requid index >=0 and index<=size");
}
/**
* 动态数组:当数组中已存的元素个数等于数组长度的长度时,把数组扩容这里扩容为原来的2倍;
* 但在jdk中动态数组时扩容为原来的1.5倍
*/
if(size == data.length){
resize(data.length*2);
}
/**
* 向数组指定的位置添加元素:
* 向下标为index的位置添加元素,则从数组最后一个元素(即下标为size-1的元素)到下标为index的元素都要
* 依次往后移动一位
*/
//1、移动index及其以后的元素
for(int i = (size - 1);i>=index;i--){
data[i+1] = data[i];
}
//2、在指定的位置添加元素
data[index] = e;
size++;
}
/**
* 扩容数组
* @param i
*/
private void resize(int i) {
E[] arr = (E[])new Object[i];
for(int j = 0;j<data.length;j++){
arr[j] = data[j];
}
//把数组data指向新数组
data = arr;
}
/**
* 查找数组指定位置的元素
* @param index
* @return
*/
public E get(int index){
if(index < 0 || index>=size){
throw new IllegalArgumentException("get filed,index is not");
}
return data[index];
}
/**
* 取数组第一个元素
* @return
*/
public E getFirst(){
return get(0);
}
/**
* 取数组最后一个元素
* @return
*/
public E getLast(){
return get(size-1);
}
/**
* 判断元素e是否包含在数组中
* @param e
* @return
*/
public boolean contains(E e){
for(int i=0;i<size;i++){
if(data[i] == e){
return true;
}
}
return false;
}
/**
* 返回元素e在数组中的位置
* @param e
* @return
*/
public int find(E e){
for(int i = 0;i<size;i++){
if(data[i] == e){
return i;
}
}
return -1;
}
/**
* 删除指定位置的元素,并把要删除的元素返回
* @param index
* @return
*/
public E remove(int index){
if(index < 0 || index>=size){
throw new IllegalArgumentException("get filed,index is not");
}
/**
*删除数组元素时,若数组元素的个数小于等于数组长度的1/2时,为了节省空间可以把数组扩容
*为原来的1/2
*/
if(size <= (data.length/2)){
resize(data.length/2);
}
E arr = data[index];
/**
* 把index后面的元素一次往前移动一位
*/
for(int i=index+1;i<size;i++){
data[i-1] = data[i];
}
size--;//删除元素后size-1
return arr;
}
//删除数组第一个元素
public E removeFirst(){
E arr = remove(0);
return arr;
}
//删除数组最后一个元素
public E removeLast(){
E arr = remove(size-1);
return arr;
}
}