[数据结构与算法]-用Java实现简单的ArrayList

版权声明:本文为博主原创文章,转载时请注明出处,谢谢!喝酒不骑马 邮箱[email protected] https://blog.csdn.net/Colton_Null/article/details/80638072

本文欢迎转载,转载前请联系作者,经允许后方可转载。转载后请注明出处,谢谢! http://blog.csdn.net/colton_null 作者:喝酒不骑马 Colton_Null from CSDN


一.引言

学习数据结构最好的方法个人总结即为两点:1.阅读源码。2.自己动手实现

本文分享一下自主实现简单ArrayList的代码,主要参考了《数据结构与算法分析》。

二.需要实现的内容

  1. size():返回当前元素个数。
  2. isEmpty():判断集合是否为空。
  3. trimToSize():将列表容量裁剪成与元素个数相等。
  4. length():返回列表容量。
  5. ensureCapacity(int newCapacity)列表扩容。
  6. get(int index):根据索引获取元素。
  7. set(int index, T t):根据索引替换元素。
  8. add(int index, T t)/add(T t):添加元素到索引位置或添加元素到末位。
  9. toString():遍历集合返回集合内容。
  10. iterator():获取迭代器。
  11. class ArrayListIterator implements Iterator:实现内部迭代器类
  12. hasNext():判断是否有下一个元素。
  13. next():获取当前迭代器迭代的元素
  14. remove():移除元素
  15. 编写测试类。

三.MyArrayList代码

import java.util.*;

public class MyArrayList<T> implements Iterable<T> {
    // 默认容量
    private static final int DEFAULT_CAPACITY = 10;

    // 列表元素个数
    private int theSize;
    // 列表元素
    private T[] theItems;

    public MyArrayList() {
        clear();
    }

    /**
     * 清空列表,创建默认长度List
     */
    public void clear() {
        theSize = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    /**
     * 返回当前列表元素个数
     *
     * @return
     */
    public int size() {
        return theSize;
    }

    /**
     * 判断列表是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 将列表容量裁剪成跟元素个数一致
     */
    public void trimToSize() {
        ensureCapacity(size());
    }

    /**
     * 列表长度
     *
     * @return
     */
    public int length() {
        return theItems.length;
    }

    /**
     * 扩容
     *
     * @param newCapacity 容量大小
     */
    public void ensureCapacity(int newCapacity) {
        if (newCapacity < theSize) {
            return;
        }
        T[] old = theItems;
        theItems = (T[]) new Object[newCapacity];
        for (int i = 0; i < size(); i++) {
            theItems[i] = old[i];
        }
    }

    /**
     * 根据索引获取列表值
     *
     * @param index 索引值
     * @return 该索引下的元素
     */
    public T get(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return theItems[index];
    }

    /**
     * 替换索引所在位置的元素
     *
     * @param index 索引值
     * @param t     新元素
     * @return 旧元素
     */
    public T set(int index, T t) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        T old = theItems[index];
        theItems[index] = t;
        return old;
    }

    /**
     * 添加元素到索引位置
     *
     * @param index 索引值
     * @param t     新元素
     */
    public void add(int index, T t) {
        if (theItems.length == size()) {
            // "+1是用来处理size()为0时的情况
            ensureCapacity(size() * 2 + 1);
        }
        // 索引后的元素依次后移一位
        for (int i = size(); i > index; i--) {
            theItems[i] = theItems[i - 1];
        }
        theItems[index] = t;
        theSize++;
    }

    /**
     * 添加元素到列表末位
     *
     * @param t 新元素
     */
    public void add(T t) {
        add(size(), t);
    }

    /**
     * 移除索引所在位置元素
     *
     * @param index 索引值
     * @return 被移除的元素
     */
    public T remove(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        T rmT = theItems[index];
        // 索引后的所有元素前移一位
        for (int i = index; i < size() - 1; i++) {
            theItems[i] = theItems[i + 1];
        }
        theSize--;
        return rmT;
    }

    @Override
    public String toString() {
        String str = "";
        for (int i = 0; i < size(); i++) {
            if (theItems[i] != null) {
                str += theItems[i].toString() + "\n";
            } else {
                str += "null\n";
            }
        }
        return str;
    }

    /**
     * 获得该列表的迭代器
     *
     * @return
     */
    @Override
    public Iterator<T> iterator() {
        return new ArrayListIterator();
    }

    /**
     * 内部类,迭代器
     */
    private class ArrayListIterator implements Iterator<T> {

        // 记录当前索引,默认为0
        private int current = 0;

        /**
         * 判断元素是否存在
         *
         * @return
         */
        @Override
        public boolean hasNext() {
            return current < size();
        }

        /**
         * 获取当前迭代器迭代的元素
         *
         * @return 当前迭代器迭代的元素
         */
        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            // 获取后,current值+1
            return theItems[current++];
        }

        /**
         * 移除元素
         */
        @Override
        public void remove() {
            // 移除元素实际上是调用next()方法后,再remove。而next()后,current值被加1,是为了下次迭代做准备。
            // 所以如果想删除next()方法返回的元素,需要删除current值-1后的索引所在的元素。
            // 又因为移除元素后,后面的元素位置发生了变化,所以current必须的值必须-1。所以使用--。
            MyArrayList.this.remove(--current);
        }
    }
}

四.MyArrayListTest代码

测试方法和思路都写在注释里了。

import java.util.Iterator;

public class MyArrayListTest {
    public static void main(String[] args) {
        MyArrayList<Integer> list1 = new MyArrayList<>();
        // 测试List初始化内容
        System.out.println("list1的元素个数为:" + list1.size());
        System.out.println("list1为空:" + list1.isEmpty());
        System.out.println("list1的长度为:" + list1.length());

        // 测试添加元素
        list1.add(1);
        list1.add(2);
        System.out.println("list1的第一个元素为:" + list1.get(0));

        // 测试插入元素
        list1.add(0, 100);
        System.out.println("list1的第一个元素为:" + list1.get(0));

        // 测试更新元素
        list1.set(1, 200);
        System.out.println("list1的第一个元素为:" + list1.get(1));

        // 测试移除元素
        list1.remove(2);
        System.out.println("list1的元素为:");

        // 测试list扩容
        System.out.println(list1);
        for (int i = 3; i < 15; i++) {
            list1.add(i);
        }
        System.out.println("list1的元素为:");
        System.out.println(list1);

        // 测试list长度裁剪
        System.out.println("list1的长度为:" + list1.length());
        list1.trimToSize();
        System.out.println("trimToSize后,list1的长度为:" + list1.length());

        // 测试迭代器
        Iterator itr = list1.iterator();
        System.out.println("用迭代器遍历输出list1");
        while (itr.hasNext()) {
            System.out.println(itr.next().toString());
        }

        // 测试迭代器删除元素
        itr = list1.iterator();
        while (itr.hasNext()) {
            itr.next();
            itr.remove();
        }
        System.out.println("list1为空:" + list1.isEmpty());
    }
}

输出结果

list1的元素个数为:0
list1为空:true
list1的长度为:10
list1的第一个元素为:1
list1的第一个元素为:100
list1的第一个元素为:200
list1的元素为:
100
200

list1的元素为:
100
200
3
4
5
6
7
8
9
10
11
12
13
14

list1的长度为:21
trimToSize后,list1的长度为:14
用迭代器遍历输出list1
100
200
3
4
5
6
7
8
9
10
11
12
13
14
list1为空:true

证明MyArrayList的简单实现可用。


站在前人的肩膀上前行,感谢以下博客及文献的支持。

  • 《数据结果与算法分析 机械工业出版社》

猜你喜欢

转载自blog.csdn.net/Colton_Null/article/details/80638072