小肥柴慢慢学习数据结构笔记(Java篇)(1-1 动态数组ArrayList)

小肥柴慢慢学习数据结构笔记(Java篇)(1-1 动态数组ArrayList)

目录

在链接 小肥柴慢慢手写数据结构(C篇)(1-3 线性表 ArrayList 严版教材实现浅析).的最后部分,给出了大佬的git仓,现在就跟着大佬的脚步用java再写一遍(Java和C++都是面向对象的,写起来顺畅很多)

1-1 上代码

  1. MyArrayList.java
public class MyArrayList<E> {
	private static final int DEFAULT_CAPACITY = 20;
	private static final int INVALID_INDEX = -1;

	private E[] data;
	private int size = INVALID_INDEX;

	public MyArrayList() {
		this(DEFAULT_CAPACITY);
	}

	public MyArrayList(int capacity) {
		data = (E[]) new Object[capacity];
		size = 0;
	}

	public int getSize() {
		return size;
	}

	public int getCapacity() {
		return data.length;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public int find(E e) {
		for (int i = 0; i < size; i++)
			if (data[i].equals(e))
				return i;
		return INVALID_INDEX;
	}

	public boolean contains(E e) {
		for (int i = 0; i < size; i++)
			if (data[i].equals(e))
				return true;
		return false;
	}

	public void add(int index, E e) {
		if (index < 0 || index > size)
			throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");

		if (index == data.length)
			resize(data.length << 1);

		for (int i = size - 1; i >= index; i--)
			data[i + 1] = data[i];

		data[index] = e;

		size++;
	}

	public void addLast(E e) {
		add(size, e);
	}

	public void addFirst(E e) {
		add(0, e);
	}

	public E remove(int index) {
		if (index < 0 || index >= size)
			throw new IllegalArgumentException("remove failed. Require index >= 0 and index < size.");

		E ret = data[index];
		for (int i = index; i < size; i++)
			data[i] = data[i + 1];
		size--;
		data[size] = null;

		if (size == (data.length >> 2) && (data.length >> 1) != 0)
			resize(data.length >> 1);

		return ret;
	}

	public E removeFirst() {
		return remove(0);
	}

	public E removeLast() {
		return remove(size - 1);
	}

	public void removeElement(E e) {
		int index = find(e);
		if (index != INVALID_INDEX)
			remove(index);
	}

	public E get(int index) {
		if (index < 0 || index >= size)
			throw new IllegalArgumentException("Get failed. Index is illegal.");
		return data[index];
	}

	public void set(E e, int index) {
		if (index < 0 || index >= size)
			throw new IllegalArgumentException("Set failed. Index is illegal.");
		data[index] = e;
	}

	private void resize(int newCapacity) {
		E[] tmp = data;
		E[] newData = (E[]) new Object[newCapacity];
		for (int i = 0; i < size; i++)
			newData[i] = data[i];
		data = newData;

		tmp = null;
	}

	@Override
	public String toString() {
		StringBuilder strb = new StringBuilder();
		strb.append("[ ");
		for (int i = 0; i < size; i++)
			strb.append(data[i] + " ");
		strb.append("]");
		return strb.toString();
	}

}

  1. Main.java
public class Main {
   public static void main(String[] args) {
       MyArrayList<Integer> arr = new MyArrayList<>();
       for(int i = 0 ; i < 10 ; i ++)
           arr.addLast(i);
       System.out.println(arr);

       arr.add(1, 100);
       System.out.println(arr);

       arr.addFirst(-1);
       System.out.println(arr);

       arr.remove(2);
       System.out.println(arr);

       arr.removeElement(4);
       System.out.println(arr);

       arr.removeFirst();
       System.out.println(arr);

       for(int i = 0 ; i < 4 ; i ++){
           arr.removeFirst();
           System.out.println(arr);
       }
   }
}

1-2 代码细节

  1. 由于java中可以使用数组的length方法直接获取当前数组长度,所以不需要维护一个专门的容量(capacity)成员。
  2. Java在使用前,必须先new得到对象实例,所以也不用太关心是否存在空(NULL)对象的问题,且对于异常情况,直接抛出exception,代码简洁。
  3. 对于扩表和缩表,都使用一个函数resize完成,把如要修改的容量大小作为入参,简化了函数设计,巧妙。
  4. 扩表时,依旧采用了两倍方式,在缩表时,采用了lazy方式:当前使用量(用size标记)仅为容量(capacity)的1/4时才会触发,即满足了及时回收空间的需要,也能防止在1/2处反复添加+删除元素导致的频繁resize动作(刘大佬课程里称之为:复杂度的震荡),即反复横跳。这一点很多教材中都不作讨论的,却是很有意思且实用的一个知识点。
  5. 缩表时有一个size=1的bug,大佬也指出来并修正了。

1-3 源码阅读

网上源码解析的帖子很多,直接学习即可,对sort部分的分析,值得投入时间去看看,但已经属于算法范畴了:
(参考) 《JAVA源码分析》:ArrayList. 这个博主有很多源码解析文章
(参考) java sort排序源码分析(TimSort排序).
(参考)java中List的sort源码解读.

1-4 总结

用java相对于C能快速的实现一个较为完备的数据结构,但对比官方源码实现,还是比较简陋的,但能有就行,而且跟着大佬还能考虑一些小的细节,有收获。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值