我们已经学过了数组了,但我们知道一个事,数组是定长的,定长的数组显然是满足不了我们的需求的,因为我们不知道自己需要多长的数组,所以只能定义的尽可能大,这样就会造成极大的空间浪费。
那么我们可不可以想个办法去实现一个不固定长度的容器呢?
这节课我就来带大家实现一个不固定长度的容器。
Code:
/**
* 我的数组表
* 用数组来存储数据
*/
public class MyArrayList<E> {
//存储数据
private Object[] values;
//MyArrayList中存储的元素个数
private int size = 0;
//接下来写构造器
public MyArrayList()
{
values = new Object[10]; //我们默认初始化数组长度为10
}
//当然你我们也应该允许自定义容器长度
public MyArrayList(int capital)
{
values = new Object[capital];
}
//定义一个获取MyArrayList内存储元素个数的方法
public int size()
{
return size;
}
//核心方法,添加元素
public void add(E e)
{
//再添加元素之前需要做判断
if (size == values.length)
{
expandCapital();
}
//这个其实不难,就是往数组里添加元素
values[size] = e;
size++;
}
//扩容
private void expandCapital()
{
if (size == values.length)
{
Object[] newValues = new Object[size * 2]; //我们将数组长度扩大一倍
//然后拷贝数据
for (int i = 0; i < size; i++) {
newValues[i] = values[i];
}
//让values指向扩容后的数组
values = newValues;
}
}
//接下来我们需要有一个获取元素的方法
public E get(int index)
{
//这里还有点小问题,没有防止数组越界,加个判断
if (index < 0 || index >= size)
return null;
return (E)values[index];
}
//有添加就要有删除
/**
* 删除方法,删掉index位置的元素,并返回被删掉的元素
* @return
*/
public E delete(int index)
{
//第一步,找到要被删除的元素
E e = get(index);
if (e != null)
{
//开始删除,想法就是让a[i] = a[i+1],然后让最后一个元素指向null,最后size--
for (int i = index; i < size - 1; i++)
values[index] = values[index + 1];
values[size - 1] = null;
size--;
}
//如果e为null
return null;
}
//再来写一个修改
public void set(int index, E e)
{
if (get(index) != null)
{
values[index] = e;
}
}
//最后写一个insert,在任意位置插入
public void insert(int index, E e)
{
//首先做判断,插入位置是否合法
if (index < 0 || index > size())
return;
if (index == size)
add(e);
else
{
//和删除相反
add(null);
for (int i = size; i > index; i--)
{
values[i] = values[i-1];
}
values[index] = e;
return;
}
}
public boolean contains(E e)
{
//如果e为null就检查一下表里有没有null
if (e == null)
{
for (int i = 0; i < size; i++) {
if (values[i] == null)
return true;
}
}
else
{
//如果e不为null就调用equals方法判断表里是否有元素和e相等
for (int i = 0; i < size; i++) {
if (e.equals(values[i]))
return true;
}
}
return false;
}
//注意,这里必须new一个新的数组返回,因为我们不希望返回的数组是values引用的数组对象
public Object[] toArray()
{
Object[] newValues = new Object[this.size()];
for (int i = 0; i < size; i++) {
newValues[i] = values[i];
}
return newValues;
}
//将数组复制到arr中,只不过这个传入的数组长度必须要足够长
public void toArray(E[] arr)
{
if (arr.length < size)
{
System.out.println("这个数组长度小于" + this.size() + ", 请传入一个长度比" + this.size() + "更长的数组");
return;
}
for (int i = 0; i < size; i++) {
arr[i] = (E)values[i];
}
}
public static void main(String[] args) {
MyArrayList<Integer> list = new MyArrayList<>();
list.add(1);
list.add(2);
System.out.println(list.size()); //2
//可以看到我们可以动态的添加数据,但有一个问题
for (int i = 0; i < 100; i++)
{
list.add(i);
}
//数组下标越界了,但是我们希望我们可以添加任意个元素,怎么办呢?
//一个想法是数组扩容
System.out.println("添加100个元素后的表的长度:" + list.size());
//测试一下
System.out.println("第50个元素为:" + list.get(50));
System.out.println("第51个元素为:" + list.get(51));
System.out.println("我要删除第50个元素啦");
list.delete(50);
System.out.println("现在第50个元素为:" + list.get(50));
System.out.println("现在表的长度为:" + list.size());
//可以很明显的看到元素被删除了
//试试可不可以
System.out.println("现在我要在表的第50位置插入48");
list.insert(50,48);
System.out.println("现在表的第50位置的元素为:" + list.get(50));
System.out.println("现在表的长度为:" + list.size());
//这就是动态数组表的增删改查
//最后再加点其他功能
System.out.println(list.contains(60));
Object[] objects = list.toArray();
System.out.println(objects.length);
Integer[] arr = new Integer[30];
list.toArray(arr); //这样就长度不够
Integer[] arr2 = new Integer[200];
list.toArray(arr2);
System.out.println(arr2[0]); //这个就正常了
}
}