重生之我要学数据结构---动态数组

动态数组

动态数组三姐妹:大小、容量、静态数组。

public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];
}

接下来就是熟悉的增删改查环节了。

添加

添加在哪加呢,尾部啦!

public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }
}

但是我现在不想在尾部添加,我想在哪加就在哪加。OK,满足!

public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }

        array[index] = addNum;
        size++;
    }
}

这里也可以用循环移位来实现。

查找

就直接上代码了。

public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }

        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }
}

遍历

接下来就是我们要封装遍历操作了。

方式1:普通方式

普通方式就是通过普通的循环遍历。

public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }

        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }
}
方式2:函数式接口—Consumer
public class DynamicArray {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }
        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }

	// 遍历---函数式接口
    public void froeach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }
}

测试代码:

@Test
public void test2() {
    DynamicArray dynamicArray = new DynamicArray();

    dynamicArray.addLast(1);
    dynamicArray.addLast(2);
    dynamicArray.addLast(3);
    dynamicArray.addLast(4);
    dynamicArray.addLast(5);

    dynamicArray.froeach(element -> System.out.println(element));
}

这里的lambda表达式也可以用方法引用来替代哈~

方式3:迭代器

实现迭代器之前要先实现接口Iterable。
实现迭代器要重写两个方法:hasNext()、Next()。

public class DynamicArray implements Iterable<Integer> {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }
        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }

	// 遍历---函数式接口
    public void froeach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

	// 遍历---迭代器
    public Iterator<Integer> iterator() {
        // 匿名实现类的匿名对象
        return new Iterator<Integer>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i < size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }
}
方式4:流
public class DynamicArray implements Iterable<Integer> {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }
        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }

	// 遍历---函数式接口
    public void froeach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

	// 遍历---迭代器
    public Iterator<Integer> iterator() {
        // 匿名实现类的匿名对象
        return new Iterator<Integer>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i < size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

	// 遍历---流实现
    public IntStream stream() {
        return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
    }
}

遍历方式大概是这几种方式。
接下来就是删除操作。

删除

public class DynamicArray implements Iterable<Integer> {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = new int[capacity];

	// 添加
	public void addLast(int addNum) {
        array[size++] = addNum;
    }

	    public void add(int addNum, int index) {// index---索引
        // 边界安全
        if (index >= 0 && index < size) {
            System.arraycopy(array, index, array,
                    index + 1, size - index);
        }
        array[index] = addNum;
        size++;
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }

	// 遍历---函数式接口
    public void froeach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

	// 遍历---迭代器
    public Iterator<Integer> iterator() {
        // 匿名实现类的匿名对象
        return new Iterator<Integer>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i < size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

	// 遍历---流实现
    public IntStream stream() {
        return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
    }

	// 删除
    public int remove(int index) {// 返回被删除的元素
        int removedNun = array[index];
        System.arraycopy(array, index + 1,
                array, index, size - index - 1);
        size--;
        return removedNun;
    }
}

基本操作已经结束了,现在我们再思考之前的添加操作。
既然是动态数组,扩容是必然的,所以我们的添加操作要考虑扩容。
并且可以对addLast方法进行发代码层面的优化,它可以调用add方法。
对于一开始我们就给我们的静态数组分配了空间,如果长时间不用,在内存中会长时间占据空间,因此可以参考设计模式中的懒汉式单例。

public class DynamicArray implements Iterable<Integer> {
    // 属性:大小、容量、静态数组
    private int size = 0;
    private int capacity = 8;
    private int[] array = {};// 类似懒汉式

	// 添加
	public void addLast(int addNum) {
        add(addNum, size);
    }

   	public void add(int addNum, int index) {
       	checkAndGrow();

       	// 添加逻辑
       	if (index >= 0 && index < size) {
           	// 向后挪动, 空出待插入位置
           	System.arraycopy(array, index,
                   	array, index + 1, size - index);
       	}
       	array[index] = addNum;
       	size++;
   	}

    private void checkAndGrow() {
        // 容量检查
        if (size == 0) {
            array = new int[capacity];
        } else if (size == capacity) {
            // 进行扩容, 扩为原来的1.5倍
            capacity += capacity >> 1;
            int[] newArray = new int[capacity];
            System.arraycopy(array, 0,
                    newArray, 0, size);
            array = newArray;
        }
    }

	// 查找
    public int get(int index) {
        if (index >= 0 && index < size) {
            return array[index];
        }
        throw new RuntimeException("角标越界");
    }

	// 遍历---普通实现
    public void froeach() {
        for (int i = 0; i < size; i++) {
            System.out.println(array[i]);
        }
    }

	// 遍历---函数式接口
    public void froeach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

	// 遍历---迭代器
    public Iterator<Integer> iterator() {
        // 匿名实现类的匿名对象
        return new Iterator<Integer>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i < size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

	// 遍历---流实现
    public IntStream stream() {
        return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
    }

	// 删除
    public int remove(int index) {// 返回被删除的元素
        int removedNun = array[index];
        System.arraycopy(array, index + 1,
                array, index, size - index - 1);
        size--;
        return removedNun;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值