动态数组
之前我们一直实现的是静态数组,并不能满足我们对于数组大小的灵活性,当我们想要向数组中添加数据时,发现我们的数组已经没有内存空间了,这个时候我们应该怎么办?其实简单的方法就是,我们重新开辟一个空间,比如数组的大小是之前的两倍,然后再把之前的数组的内容一个个重新复制到新数组中,进而往后添加我们想要的数组内容。而之前的数组,由于没有对象指引,java的垃圾回收机制就会自动的帮助我们处理掉这个不用的内存空间。
在之前代码的基础上,我们只需要重新添加一个新的方法:
// 定义新数组,容量是之前的两倍,并让老数组中指向新数组
private void resize(int newCapacity){
E[] newData=(E[]) new Object[newCapacity];// 强制类型转换
for (int i = 0; i < size; i++) {
newData[i]=data[i];
}
data=newData;
}
这个方法的调用,我们放在数组的add(添加)方法上,在添加数据之前,首先判断数组是不是已经放满了数据,如果已经满了,我们就可以调用这个方法。另外我们也可以在删除数据的方法中使用,如果数组中存放数据的大小小于容量的一半,我们就传入之前一半的容量参数,进行调用这个方法。
具体的实现代码如下:(也是在之前的基础上略微修改了代码)
public class ArrayFDyn <E>{
// 成员变量
private E[] data;
private int size;
// 有参构造,传入数组的容量capacity
public ArrayFDyn(int capacity){
data = (E[])new Object[capacity]; // 强制类型转换
size=0;
}
// 无参构造,默认容量是10
public ArrayFDyn(){
this(10);
}
// 获取数组的元素个数
public int getSize(){
return size;
}
// 获取数组的容量
public int getCapacity(){
return data.length;
}
// 判断数组是否为空
public boolean isEmpty(){
return size==0;
}
// 向数组末尾添加元素e
public void addLast(E e){
add(size,e);
}
// 在数组的第一个位置添加元素e
public void addFirst(E e){
add(0,e);
}
// 向指定index的位置添加元素e
public void add(int index,E e){
if(index<0 || index>size){
throw new IllegalArgumentException("Add Failed. Require index>=0 and index<=size.");
}
if(size == data.length){
resize(2* data.length);
}
for (int i = size-1; i >= index; i--) {
data[i+1]=data[i];
}
data[index]=e;
size++;
}
// 获取index指定位置的元素
public E get(int index){
if(index<0|| index>=size){
throw new IllegalArgumentException("Get Failed. Index is illegal.");
}
return data[index];
}
// 修改index索引位置的元素为e
public void set(int index,E e){
if(index<0|| index>=size){
throw new IllegalArgumentException("Get Failed. Index is illegal.");
}
data[index]=e;
}
// 查找数组中是否包含元素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;
}
// 删除指定索引index的位置,并返回删除的元素
public E remove(int index){
if(index<0|| index>=size){
throw new IllegalArgumentException("Remove Failed. Index is illegal.");
}
E ret=data[index];
for (int i = index+1; i <size ; i++) {
data[i-1]=data[i];
}
size--;
// 我们也可以判断删除后数组容量,如果size==容量的一半,我们就可以删除一半的容量
if(size== data.length/2){
resize(data.length/2);
}
return ret;
}
//从数组中删除第一个元素,并返回
public E removeFirst(int index){
return remove(0);
}
//从数组中删除最后一个元素,并返回
public E removeLast(int index){
return remove(size-1);
}
// 从数组中删除元素e
public void removeElement(E e){
int index=find(e);
if(index!=-1){
remove(index);
}
}
// 重新数组的toString的方法
@Override
public String toString() {
StringBuilder res=new StringBuilder();
res.append(String.format("Array:size=%d,capacity=%d\n",size,data.length));
res.append("[");
for (int i = 0; i < size; i++) {
res.append(data[i]);
if(i!=size-1){
res.append(", ");
}
}
res.append("]");
return res.toString();
}
// 定义新数组,容量是之前的两倍,并让老数组中指向新数组
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 static void main(String[] args) {
Array arr = new Array(20);
for (int i = 0; i < 10; i++) {
arr.addLast(i);
}
System.out.println(arr);
arr.add(0,100);
System.out.println(arr);
arr.remove(2);
System.out.println(arr);
arr.removeElement(100);
System.out.println(arr);
}
}