Java泛型数组实现动态扩容和元素操作

        在Java中,数组是一种非常基础且重要的数据结构,它可以存储多个相同类型的元素。然而,数组的长度是固定的,一旦创建就无法改变,这给我们的开发带来了一些限制。为了解决这个问题,我们可以使用泛型来实现动态扩容的数组,即在数组元素达到上限时,自动创建一个更大容量的新数组并将原数组元素复制过去。本文将详细介绍如何使用泛型数组实现动态扩容和元素操作,并提供一些注意事项和相关知识。

        

import java.sql.Array;
import java.util.Arrays;
// 泛型: 类型模板 类名的后面 <E> 表示一个类型
// 泛型不能创建对象 不能new
public class MyArray<E> {
    Object[] values;
    int size;
    int length;

    public MyArray(int initLength) {
        if (initLength <= 1) {
            throw new IllegalArgumentException("不合法的参数");
        }
        values = new Object[initLength];
        size = 0;
        length = initLength;
    }

    private void grow(int min) {
        int oldLength = length;
        int newLength = oldLength + (oldLength >> 1);
        if (newLength < oldLength + min) {
            oldLength = oldLength + min;
            newLength = oldLength + (oldLength >> 1);
        }
        Object[] newValues = new Object[newLength];
        for (int i = 0; i < values.length; i++) {
            newValues[i] = values[i];
        }
        values = newValues;
        length = newLength;
        System.out.println("扩容后的长度:" + length);
    }

    public void add(E e) {
        if (size == length) {
            grow(1);
        }
        values[size++] = e;
    }

    public void addAll(E[] e) {
        if (size + e.length >= length) {
            int min = e.length - (length - size);
            grow(min);
        }
        for (int i = 0; i < e.length; i++) {
            values[size++] = e[i];
        }
    }

    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException("传入下标索引越界");
        }
        return (E) values[index];
    }

    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException("传入下标索引越界");
        }
        E old = (E) values[index];
        for (int i = index; i < size - 1; i++) {
            values[i] = values[i + 1];
        }
        size--;
        values[size] = null;// 清除最后一个
        return old;
    }

    // 移除多个
    public int removeEle(E e) {
        int count = 0;
        for (int i = 0; i < size; i++) {
            if (values[i].equals(e)) {
                count++;
                remove(i);
            }
        }
        return count;
    }

    public void removeAll(int si, int ei) {
        if (si < ei && si >= 0 && ei < size) {
            for (int i = si; i <= ei; i++) {
                if ((ei + i) < size) {
                    values[i] = values[ei + i];
                } else {
                    values[i] = null;
                }
            }
            size -= (ei - si);
        }
    }

    // 排序
    public static void main(String[] args) {
        MyArray myArray = new MyArray(10);
        for (int i = 0; i < 150; i++) {
            myArray.add(i);
            myArray.add("hello");
            myArray.add(1.2 * i);
        }
        Object[] objects = new Object[160];
        for (int i = 0; i < objects.length; i++) {
            objects[i] = i + 100;
        }
        // myArray.addAll (objects);
        // System.out.println ((163 + 147) + (163 + 147) / 2);
        myArray.removeAll(2, 100);
        System.out.println(Arrays.toString(myArray.values));
        // 定义在类上的时候 就是一个符号 表示一种类型
        // 创建对象时指代具体的类型
        MyArray<String> strList = new MyArray<>(10);
        for (int i = 0; i < 5000; i++) {
            strList.add("Hello" + i);
            // strList.add (i);
        }
        String str = strList.get(50);
        System.out.println(str);
    }
}

代码解析: 上述代码是一个名为MyArray的泛型类,它实现了动态扩容和元素操作的功能。以下是代码的主要部分:

  1. 构造函数:通过传入初始长度来创建MyArray对象,如果初始长度小于等于1,则抛出IllegalArgumentException异常。

  2. 动态扩容:当数组元素达到上限时,调用grow()方法进行扩容。该方法会根据算法计算出新数组的长度,并将原数组元素复制到新数组中。

  3. 添加元素:add()方法用于向数组中添加元素。如果数组已满,则先调用grow()方法进行扩容,然后将元素添加到数组末尾。

  4. 批量添加元素:addAll()方法用于从一个数组中批量添加元素到当前数组。如果当前数组的容量不足以容纳所有元素,则先调用grow()方法进行扩容,然后将元素逐个添加到数组末尾。

  5. 获取元素:get()方法用于根据索引获取数组中的元素。如果索引越界,则抛出ArrayIndexOutOfBoundsException异常。

  6. 删除元素:remove()方法用于根据索引删除数组中的元素。如果索引越界,则抛出ArrayIndexOutOfBoundsException异常。删除元素后,将后续元素向前移动一个位置,并将最后一个位置置为null。

  7. 批量删除元素:removeEle()方法用于删除数组中与指定元素相等的所有元素,并返回删除的数量。

  8. 区间删除元素:removeAll()方法用于删除数组中指定索引范围内的元素。删除元素后,将后续元素向前移动,同时将末尾位置设为null。

  9. 示例:代码的末尾给出了使用示例,展示了如何创建MyArray对象、添加元素、扩容、删除元素等操作。

注意事项和知识:

  1. 泛型数组的创建:在Java中,我们不能直接创建泛型数组,因此我们使用Object类型数组来代替。这样做的原因是Java的泛型是在编译期进行类型擦除的,编译后的字节码中不包含泛型的信息。因此,在数组中使用泛型时,会出现警告信息。

  2. 类型转换:在代码中,我们使用强制类型转换将Object类型转换为泛型类型。需要注意的是,在进行强制类型转换时,要确保类型的兼容性,否则可能会引发ClassCastException异常。

  3. 动态扩容的思路:在MyArray类中,我们定义了一个动态扩容的方法grow()。该方法根据算法计算出新数组的长度,并将原数组元素复制到新数组中。常见的扩容算法是每次扩容增加当前数组长度的一半。

  4. 索引越界检查:在操作数组元素时,需要进行索引越界检查。如果索引超出了有效范围,可以通过抛出ArrayIndexOutOfBoundsException异常来提示错误。

  5. 删除元素的维护:在删除元素后,需要将后续元素向前移动一个位置,并将最后一个位置置为null。这样可以确保数组的连续性,并避免悬空引用导致内存泄漏。

  6. 批量删除元素的效率:在removeEle()方法中,我们使用循环逐个删除与指定元素相等的所有元素。这种方法的时间复杂度为O(n^2),对于大量元素的情况下,效率较低。如果需要高效删除大量元素,可以考虑使用其他数据结构,如链表或集合。

  7. 泛型类型推断:在代码示例中,我们使用了菱形操作符<>来进行泛型类型推断。这种写法可以简化代码,并提高可读性。

总结: 通过使用泛型数组实现动态扩容和元素操作,我们可以更灵活地处理数据,并提高代码的可维护性和可复用性。在实际开发中,我们需要注意泛型数组的创建方式、类型转换的安全性、索引越界的检查以及删除元素后的维护等问题。同时,对于大量元素的批量删除操作,需要考虑选择合适的数据结构来提高效率。希望本文对于理解泛型数组的实现和相关知识有所帮助。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值