使用java语言实现一个动态数组(详解)(数据结构)
? 废话不多说,上代码 1.从类名开始(我真是太贴心了,给自己点个赞) public class Array<E> 首先数组类需要带有泛型,这个不多说。需要注意的是在java中,数组只能存放同一个类型的。
private int size; //数组中元素的个数 private E[] data; //数组声明
for (int i = 0; i < size; i++) { }
学习的本质就是将复杂的东西简单化。 ? public Array (int capacity) { data = (E[])new Object[capacity]; size = 0; } public Array () { this(10); //调用另一个构造方法,并默认初始容量为10 }
//获得数组元素个数 public int getSize () { return size; } //获得数组长度 public int getCapacity () { return data.length; } //获得数组是否为空 public boolean isEmpty () { return size == 0; } ? 5.添加方法 数组添加的本质就是:从后往前到指定索引位置,每个元素向后移一个格,给新来的腾出个地方。
重点:从后往前
//向数组指定位置添加元素,index为指定索引位置,e为添加的值 public void add (int index,E e) { //索引位置不能让它瞎插,索引为负数,或者跳格子插,不可以。 if (index < 0 || index > size) { throw new IllegalArgumentException("add is fail,require index < 0 || index > size"); } //当数组容量满了的时候,调用扩容方法,此处给它扩当前数组长度的两倍。 if (data.length == size) { this.resize(data.length * 2); }for (int i = size - 1; i >= index; i--) { data[i+1] = data[i]; } //新来的进坑 data[index] = e; //维护size size ++; } ? //向数组第一位添加元素 public void addFirst (E e) { //直接复用上一个add方法 this.add(0,e); } //向数组最后一位添加元素 public void addLast (E e) { //同理 this.add(size,e); } ?
删除的本质:和添加相反,从要删除的索引位置的下一位开始,到最后一位元素索引位置结束,依次向前占一个坑。
重点:遍历的时候从前往后
//根据索引删除某个元素 返回删除的元素 public E remove (int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("remove is fail,require index < 0 || index >= size"); } //先把要删除的元素存起来,不然等会就给覆盖了。 E value = data[index]; for (int i = index + 1; i < size; i++) { data[i-1] = data[i]; } //维护size size --; //此处为什么设置为null呢,因为泛型的原因,传进来的都是类对象,数组中存的是引用地址,引用不断开的话,垃圾回收器没办法回收。 data[size] = null; //此处缩容,当数组元素个数等于数组长度四分之一时,进行缩容
? //根据值删除某个元素 public void removeByValue (E e) { //复用根据值查找元素的方法,返回索引(此方法在下面) int index = this.getByElement(e); if (index != -1) { //复用根据索引删除的方法 this.remove(index); } } //删除第一个元素 public E removeFirst () { return this.remove(0); } //删除最后一个元素 public E removeLast () { return this.remove(size - 1); } ?
//根据索引查找数组某个元素,返回值 public E getByIndex (int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("get is fail,require index < 0 || index >= size"); } return data[index]; } ? //根据值查找数组某个元素,返回索引 public int getByElement (E e) { //本质:遍历数组进行比对 for (int i = 0; i < size; i++) { if (data[i].equals(e) ) { return i; } } return -1; } ? //是否包含该元素 public boolean contains (E e) { //本质:遍历数组进行比对 for (int i = 0; i < size; i++) { if (data[i].equals(e)) { return true; } } return false; } ?
//修改数组某个元素 public void set (int index,E e) { if (index < 0 || index >= size) { throw new IllegalArgumentException("set is fail,require index < 0 || index >= size"); } data[index] = e; } ?
private void resize (int newCatacity) { E[] newData = (E[])new Object[newCatacity]; for (int i = 0; i < size; i++) { newData[i] = data[i]; } //给成员变量data重新赋值新引用(后面有内存图介绍) data = newData; } 画个扩容引用转换的内存图 测试代码 public static void main(String[] args) { Array<Integer> array = new Array(5); array.addLast(1); array.addLast(2); array.addLast(3); array.addLast(4); array.addLast(5); } ? ? ? ?
@Override public String toString () { StringBuilder stringBuilder = new StringBuilder(); //Format(String,Object,Object) 将指定的 String 中的格式项替换为两个指定的 Object 实例的值的文本等效项。 stringBuilder.append(String.format("size =%d,capacity =%dn ",size,data.length)); stringBuilder.append(‘[‘); for (int i = 0; i < size; i++) { stringBuilder.append(data[i]); if (i != size -1) { stringBuilder.append(‘,‘); } } stringBuilder.append(‘]‘); return stringBuilder.toString(); } ? 最后, 浮于表面看千遍, 不如自己思一遍, 希望这篇文章能够对你起到帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |