Java入门--简单学会泛型动态数组的编写

目录

一、如何实现一个泛型动态数组

泛型动态数组的定义

二、泛型动态数组的基本操作

1.size()和isEmpty()

2、add(T e)和addAll(T[] array)

3、insert(int index, T e)

4、get(int index)和replace(int index, T e)

5、remove(int index)和removeRange(int start, int end)

三、toString方法的重写

四、对泛型动态数组的测试


一、如何实现一个泛型动态数组

动态数组是一种常用的数据结构,它可以根据需要自动调整大小,而不需要事先指定数组的长度。在Java中,我们可以使用ArrayList类来创建一个动态数组,但是它只能存储Object类型的元素,如果我们想要存储其他类型的元素,例如int,double,String等,我们就需要进行类型转换,这会增加代码的复杂度和出错的风险。为了解决这个问题,我们可以使用泛型来实现一个动态数组,泛型可以让我们在编译时指定元素的类型,从而避免类型转换和提高代码的安全性和可读性。

泛型动态数组的定义

要实现一个泛型动态数组,我们首先需要定义一个泛型类,使用尖括号(<T>)来表示泛型参数T,T可以是任意的引用类型。然后,我们需要定义一个内部的数组来存储元素,由于Java不支持直接创建泛型数组,我们需要使用Object类型的数组,并在合适的地方进行强制类型转换。此外,我们还需要定义两个变量来记录数组的长度和元素的个数,分别为length和size。最后,我们需要提供一个构造方法来初始化数组,并检查参数是否合法。

public class MYArray<T>{
    T[] array; //内部数组
    int size; //元素个数
    int length; //数组长度
    public MYArray(int initLength){ //构造方法
        if(initLength <= 1){ //检查参数是否合法
            throw new RuntimeException("数组长度必须大于1");
        }
        array = (T[]) new Object[initLength]; //创建Object类型的数组并强制转换为泛型类型
        length = initLength; //初始化数组长度
        size = 0; //初始化元素个数
    }
}

二、泛型动态数组的基本操作

接下来,我们需要实现一些基本的操作来对泛型动态数组进行增删改查。这些操作包括:

  • size(): 返回元素个数
  • isEmpty(): 判断是否为空
  • add(T e): 在末尾添加一个元素
  • addAll(T[] array): 在末尾添加一个数组
  • insert(int index, T e): 在指定位置插入一个元素
  • get(int index): 获取指定位置的元素
  • remove(int index): 删除指定位置的元素并返回
  • removeRange(int start, int end): 删除一段元素并返回删除个数
  • replace(int index, T e): 替换指定位置的元素并返回旧值

1.size()和isEmpty()

这两个方法比较简单,只需要返回size变量和判断size是否为0即可。

1.1 返回元素个数
public int size(){ //返回元素个数
    return size;
}

1.2 判断数组是否为空
public boolean isEmpty() { //判断是否为空
    return size == 0;
}

2、add(T e)和addAll(T[] array)

这两个方法用于在末尾添加元素或者数组。首先,我们需要检查内部数组是否已满,如果是,则需要进行扩容操作,即创建一个新的两倍大小的数组,并将旧数组的元素复制到新数组中。然后,我们将要添加的元素或者数组赋值给新数组的相应位置,并更新size变量。

//2.1:添加一个元素
public void add(T e ){ //在末尾添加一个元素
    if (size == array.length) { //检查是否需要扩容
        T[] newArr = (T[]) new Object[size * 2]; //创建新的两倍大小的数组
        for (int i = 0 ; i < size; i++){ //复制旧数组的元素到新数组中
            newArr[i] = array[i];
        }
        System.out.println("扩容完成了!");
        array = newArr; //将新数组赋值给内部数组
    }
    array[size] = e; //将元素赋值给内部数组的末尾位置
    size++; //更新元素个数
}
//2.2: 添加一个数组
public int addAll(T[] array){ //在末尾添加一个数组
    if (array == null) { //检查参数是否为空
        throw new NullPointerException("Argument cannot be null.");
    }
    int count = 0; //记录添加的个数
    for (T element : array) { //遍历要添加的数组
        add(element); //调用add方法添加每个元素
        count++; //更新添加的个数
    }
    return count; //返回添加的个数
}

3、insert(int index, T e)

这个方法用于在指定位置插入一个元素。首先,我们需要检查索引是否合法,即是否在0到size之间,如果不是,则抛出异常。然后,我们需要检查内部数组是否已满,如果是,则进行扩容操作,同上。接着,我们需要从后往前遍历内部数组,将索引位置及其后面的元素都向后移动一位,为插入的元素腾出空间。最后,我们将要插入的元素赋值给索引位置,并更新size变量。

// 3.1 按照索引插入元素
public void insert(int index,T e){ //在指定位置插入一个元素
    if (index < 0 || index > size) { //检查索引是否合法
        throw new IndexOutOfBoundsException("Index out of range.");
    }
    if (size == array.length) { //检查是否需要扩容
        T[] newArr = (T[]) new Object[size * 2]; //创建新的两倍大小的数组
        for (int i = 0; i < size; i++) { //复制旧数组的元素到新数组中
            newArr[i] = array[i];
        }
        array = newArr; //将新数组赋值给内部数组
    }
    for (int i = size - 1; i >= index; i--) { //从后往前遍历内部数组
        array[i + 1] = array[i]; //将索引位置及其后面的元素都向后移动一位
    }
    array[index] = e; //将元素赋值给索引位置
    size ++; //更新元素个数
}

4、get(int index)和replace(int index, T e)

这两个方法用于获取或者替换指定位置的元素。首先,我们需要检查索引是否合法,即是否在0到size-1之间,如果不是,则抛出异常。然后,我们分别返回或者赋值给内部数组的索引位置,并更新旧值。

//4.1获取元素
public T get(int index){ //获取指定位置的元素
    if (index < 0|| index >= size){ //检查索引是否合法
        throw new IndexOutOfBoundsException("Index out of range.");
    }
    return array[index]; //返回内部数组的索引位置的元素
}
//4.2修改元素
public T replace(int index ,T e) { //替换指定位置的元素并返回旧值
    if (index < 0 || index >= size) { //检查索引是否合法
        throw new IndexOutOfBoundsException("Index out of range.");
    }
    T old = array[index]; //记录旧值
    array[index] = e; //将新值赋值给内部数组的索引位置
    return old; //返回旧值
}

5、remove(int index)和removeRange(int start, int end)

这两个方法用于删除指定位置或者一段的元素。首先,我们需要检查索引或者范围是否合法,即是否在0到size-1之间,并且start不大于end,如果不是,则抛出异常。然后,我们分别记录要删除的元素或者个数,并从前往后遍历内部数组,将要删除的位置或者范围之后的元素都向前移动一位,覆盖掉要删除的元素。最后,我们将内部数组的末尾位置或者范围置为null,并更新size变量。

//5.删除元素
public T remove(int index){ //删除指定位置的元素并返回
    if (index < 0 || index >= size) { //检查索引是否合法
        throw new IndexOutOfBoundsException("Index out of range.");
    }
    T temp = array[index]; //记录要删除的元素
    for (int i = index + 1; i < size; i++) { //从前往后遍历内部数组
        array[i - 1] = array[i]; //将要删除的位置之后的元素都向前移动一位
    }
    size--; //更新元素个数
    array[size] = null; //将内部数组的末尾位置置为null
    return temp; //返回要删除的元素
}
//5.1 删除一段元素
public int removeRange(int start,int end){ //删除一段元素并返回删除个数
    if (start < 0 || start >= size || end < 0 || end >= size || start > end) { //检查范围是否合法
        throw new IndexOutOfBoundsException("Index out of range.");
    }
    int count = 0; //记录删除的个数
    for (int i = end; i < size; i++) { //从前往后遍历内部数组
        array[i - (end - start)] = array[i]; //将要删除的范围之后的元素都向前移动end-start位
    }
    for (int i = size - (end - start); i < size; i++) { //从后往前遍历内部数组
        array[i] = null; //将内部数组的末尾范围置为null
    }
    count = end - start; //计算删除的个数
    size -= count; //更新元素个数
    return count; //返回删除的个数
}

三、toString方法的重写

在泛型动态数组中,重写toString方法的目的是为了将数组中的元素以字符串的形式输出,方便查看和调试。一种常见的重写方式是使用StringBuilder类来拼接数组中的元素,然后返回StringBuilder对象的字符串表示。

@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();
}

这个方法首先使用String.format方法来格式化数组的大小和容量,然后使用append方法来添加数组中的元素,注意在元素之间添加逗号和空格,最后在数组两端添加方括号。返回res.toString()就是数组的字符串表示。

四、对泛型动态数组的测试

最后,我们需要编写一个main方法来测试我们实现的泛型动态数组是否正确。我们可以创建一个长度为5的动态数组,并添加10个整数到数组中,然后打印出数组的大小和元素。我们还可以尝试其他操作,例如插入,获取,替换,删除等,并观察结果是否符合预期。

public static void main(String[] args) {
    //创建一个长度为5的动态数组
    MYArray<Integer> myArray = new MYArray<>(5);
    //添加10个整数到数组中
    for (int i = 0; i < 10; i++) {
        myArray.add(i + 1);
    }
    //打印数组的大小和元素
    System.out.println("The size of the array is: " + myArray.size());
    System.out.println("The elements of the array are: ");
    for (int i = 0; i < myArray.size(); i++) {
        System.out.print(myArray.get(i) + " ");
    }
}

运行结果如下:

扩容完成了!
The size of the array is: 10
The elements of the array are: 
1 2 3 4 5 6 7 8 9 10 

这样,我们就完成了一个泛型动态数组的实现和测试。希望这篇博客对你有所帮助。如果你有任何问题或者建议,请在评论区留言。谢谢你的阅读!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值