1. 首页
  2. Java基础

044-四十四、Java之手写ArrayList(上)

Java 中的ArrayList

ArrayList是基于动态数组实现的,数组具有按索引查找的特性,所以访问很快,适合经常查询的数据。其实就是对数组的操作。首先分析一下ArrayList的几个常用方法。


. add(E e) :将指定的元素添加到此列表的尾部。 . indexOf(Object o) 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。 . contains(Object o) : 如果此列表中包含指定的元素,则返回 true。 . isEmpty() :如果此列表中没有元素,则返回 true . size():返回此列表中的元素数。 . toArray():按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 . get(int index) :返回此列表中指定位置上的元素。 . set(int index, E element): 用指定的元素替代此列表中指定位置上的元素。 . remove(int index) : 移除此列表中指定位置上的元素。 . clear() : 移除此列表中的所有元素 . iterator():返回以恰当顺序在此列表的元素上进行迭代的迭代器。

这些大致是ArrayList很常用的方法,我们就一个个的来模仿这些方法,自定义个自己的MyArrayList类。

自定义的ArrayList

下面我们来自定义一个MyArrayList类。

要自定义 MyArrayList 类我们就要关心一下 ArrayList 有默认 Object 数组 elementData,和默认数组的长度 default_length,还有一个记录数组元素的数量 size,并且至少有2个构造方法,一个无参构造方法和一个含有长度的有参构造方法。

另外还有一个数组长度达到上线之后扩容。动态扩容也是 ArrayList 的核心吧。

代码演示

好了废话少说,现在开始代码演示,我不一定完全按照 ArrayList 源码来实现。

根据个人思想来实现,尽量减少逻辑判断,并且使用泛型实现,肯定不是最好的,仅供广大初学者参考吧。


public class MyArrayList<T> { /** * ArrayList主要就是操作数组所以首先需要定义一个数组 */ private Object[] elementData; /** * 数组的默认长度为3,方便测试 */ private int defaultLength = 3; /** * 记录数组元素的个数 */ private int size; /** * 默认构造 */ public MyArrayList() { /** * 调用了有参构造,传入了数组的默认3个空间 */ this(3); } /** * @param defaultLength */ public MyArrayList(int defaultLength) { if (defaultLength <= 0){ defaultLength = this.defaultLength; } elementData = new Object[defaultLength]; } }

下面开始实现各个方法了。

public boolean add(T t) 方法和扩容方法

将指定的元素添加到此列表的尾部。下面的我就直接在代码中写注释讲解了。


/** * 添加方法,将指定的元素添加到此列表的尾部。 * * @param t * @return */ public boolean add(T t) { /** * 添加之前必须检查是否需要扩容 * 这里为什么需要size+1?当size到了3之后就需要扩容了。 */ expansion(size + 1); /** * size:表示元素的索引,当前索引位置更新值之后需要自增一次,下次添加的时候也是如此 */ elementData[size++] = t; return true; } /** * 扩容方法 * 写得比较简单 * @param minLength */ private void expansion(int minLength) { /** * 首先判断目前最小长度是否超过默认长度了 * 我就不弄很复杂的算法了。直接向右移1个位加上目前的长度 */ if (minLength > this.defaultLength) { /** * 得到新的长度 */ this.defaultLength = minLength + (this.defaultLength >> 1); /** * 现在我们需要拷贝一个新的数组出来,可以使用2个方法 * 1.System.arraycopy * 2.Arrays.copyOf:这个方法简单,其实底层也是使用的System.arraycopy方法 * 拷贝elementData数据的元素到elementData,且为elementData设置一个新长度 */ elementData = Arrays.copyOf(elementData, this.defaultLength); } }

public int indexOf(T t)方法

返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。


/** * 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。 * * @param t * @return */ public int indexOf(T t) { for (int i = 0; ; i++) { /** * 保证退出的判断 */ if (i == size) { return -1; } /** * 为什么需要判断空呢,因为MyArrayList是可以存储null值的。 * 并且null值使用equals方法时会报java.lang.NullPointerException异常。 */ if (t == null && elementData[i] == null) { return i; } /** * 注意这里千万不要使用elementData[i].equals(o) * 因为elementData是可以储存null值的 * 判断时会引发java.lang.NullPointerException异常。 */ else if (t.equals(elementData[i])) { return i; } } }

public boolean contains(T t)方法

如果此列表中包含指定的元素,则返回 true。
这个方法就简单了,基本上就是调用了IndexOf方法。


/** * 如果此列表中包含指定的元素,则返回 true。 * @param t * @return */ public boolean contains(T t){ return indexOf(t) > -1; } public boolean isEmpty() 如果此列表中没有元素,则返回 true /** * 如果此列表中没有元素,则返回 true * @return */ public boolean isEmpty(){ return this.size == 0; } public int size()方法 返回此列表中的元素数。 /** * 获取数组的所有用户添加的元素数量,不是所有容量的长度 * @return */ public int size(){ return this.size; } pubilc Object[] toArray()方法 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 /** * 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有 * @return */ public Object[] toArray(){ return Arrays.copyOf(elementData,this.size); } public T get(int index)方法 返回此列表中指定位置上的元素。 /** * 返回此列表中指定位置上的元素 * @param index * @return */ public T get(int index) { arrayIndexOutOfBoundsException(index); return this.getElement(index); } /** * 有两处调用该方法,为了严谨所以封装一下 * @param index * @return */ private T getElement(int index){ return (T) this.elementData[index]; } /** * 主要是索引越界发出异常的,多处使用 * @param index */ private void arrayIndexOutOfBoundsException(int index){ /** * 在这里判断一下是想提示比较中文化。没有其它的。 */ if(index >= size || index < 0){ throw new ArrayIndexOutOfBoundsException("数组越界!!!"); } }

public void set(int index, T t)

用指定的元素替代此列表中指定位置上的元素。


/** * 用指定的元素替代此列表中指定位置上的元素。 * @param index * @param t */ public void set(int index, T t){ arrayIndexOutOfBoundsException(index); this.elementData[index] = t; }

public T remove(int index)

移除此列表中指定位置上的元素。


/** * 移除此列表中指定位置上的元素。 * 删除玩之后需要--size,并且全部都得移位 * @param index */ public T remove(int index) { arrayIndexOutOfBoundsException(index); /** * 保存删除的元素 */ T t = this.getElement(index); for (int i = index; i < this.size-1; i++) { /** * /index索引开始以后的所有元素向前移动 */ this.elementData[i] = this.elementData[i + 1]; } //设置最后一个元素为空,并且size减1 this.elementData[--this.size] = null; return t; }

public void clear()方法

移除此列表中的所有元素


/** * 移除此列表中的所有元素 */ public void clear(){ for (int i = 0; i < this.size; i++) { /** * 将所有元素赋null值 */ this.elementData[i] = null; } this.size = 0; }

备注

以上都是写了大部分了,以上可能有问题希望大家看出来了多多指正,也可以私聊小编交流。还差一个iterator()方法了留在下一节再讲。

写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:044-四十四、Java之手写ArrayList(上)

    链接:https://www.javajike.com/article/1351.html

« 045-四十五、Java之手写ArrayList(下)
043-四十三、Java之泛型详解»

相关推荐

QR code