}

数据结构_1_ArrayList

数组列表

1.接口设计

package 修炼.数据结构和算法.数据结构.List;

/**
 * @author likeLove
 * @since 2020-09-29  20:54
 * 动态数组的接口设计
 */
public interface DynamicArray<T> {
    /**
     * 获取数组元素个数
     *
     * @return 当前数组元素个数
     */
    int size();

    /**
     * 查找元素在数组中的位置
     *
     * @param o 需要查找的元素
     *
     * @return 元素在数组中的索引
     */
    int indexOf(Object o);

    /**
     * 判断元素是否存在
     *
     * @param o 元素
     *
     * @return 返回这个元素是否存在
     */
    boolean contains(Object o);

    /**
     * 判断数组是否为空
     *
     * @return 数组是否为空
     */
    boolean isEmpty();


    /**
     * 添加元素到数组
     *
     * @param o 需要添加的元素
     */
    void add(Object o);

    /**
     * 添加元素到数组的指定位置
     *
     * @param index 指定位置
     * @param o     元素
     */
    void add(int index, Object o);

    /**
     * 移除指定位置的元素
     *
     * @param index 指定位置
     *
     * @return 被移除的元素
     */
    T remove(int index);

    /**
     * 移除指定元素
     * @param o o
     * @return 被移除的元素
     */
    T remove(Object o);

    /**
     * 根据索引返回元素(从0开始)
     *
     * @param index 元素的索引
     *
     * @return 元素
     */
    T get(int index);

    /**
     * 为索引位置设置新的元素
     *
     * @param index 索引
     * @param o     新元素
     *
     * @return 旧元素
     */
    T set(int index, Object o);

    /**
     * 清空数组
     */
    void clear();
}

2.成员变量设计

    public class ArrayList<T> implements DynamicArray<T> {

    ···
        
    /**
 	* 当前数组元素个数
 	*/
    private int size;
    /**
 	* 存放元素的数组
	 */
    private Object[] elements;
    /**
 	* 默认数组大小
 	*/
    public static final int DEFAULT_CAPACITY = 10;

}

3.构造函数

public class ArrayList<T> implements DynamicArray<T> {
    ···
    /**
	 * 初始化数组大小
	 * @param capacity 数组容量
 	*/
    public ArrayList(int capacity) {
        //如果传入的数组容量大小  小于  默认的 10,就直接初始化为10
        capacity = Math.max(capacity, DEFAULT_CAPACITY);
        elements = new Object[capacity];
    }

    public ArrayList() {
        //如果不传入初始化数组容量
        this(DEFAULT_CAPACITY);
    }
    ···
}

4.完善方法

a.int indexOf(Object o)

循环遍历数组

@Override
public int indexOf(Object o) {
    // 循环遍历,判断 o 是否等于数组中对应的元素
    for (int i = 0; i < size; i++) {
        if (elements[i].equals(o)) {
            return i;
        }
    }
    return -1;
}

b.void add(int index, Object o)

  • 从数组的最后一个向前遍历到要插入的索引
  • 向后移一位
  • 插入元素
  • size++
@Override
public void add(int index, Object o) {
    // TODO likelove: 2020/10/1  动态扩容
    checkIndexOfAdd(index);
    for (int i = size; i > index; i--) {
        elements[i + 1] = elements[i];
    }
    elements[index] = o;
    size++;
}

c.T remove(int index)

  • 从索引位置开始遍历数组到size
  • 让当前元素等于当前元素的后一个
  • size- -
@Override
public T remove(int index) {
    checkIndex(index);
    Object remove = elements[index];
    for (int i = index; i < size; i++) {
        elements[i] = elements[i + 1];
    }
    size--;
    return (T) remove;
}

d.String toString()

@Override
public String toString() {
    StringBuilder sb = new StringBuilder();
    sb./*append("size = ").append(size).*/append("[");
    for (int i = 0; i < size; i++) {
        sb.append(elements[i]);
        if (i < size - 1) {
            sb.append(",").append(" ");
        }
    }
    sb.append("]");
    return String.valueOf(sb);
}

f.void checkIndex(int index)

/**
 * 检查索引是否越界
 * @param index 索引
 */
private void checkIndex(int index) {
    if (index < 0 || index >= size) {
        outOfBoundsException(index);
    }
}

/**
 * 检查索引是否越界(仅限添加方法)
 * @param index 索引
 */
private void checkIndexOfAdd(int index) {
    if (index < 0 || index > size) {
        outOfBoundsException(index);
    }
}

/**
 * 抛出数组越界异常
 * @param index 索引
 */
private void outOfBoundsException(int index) {
    throw new IndexOutOfBoundsException("index = " + index + "," + "size = " + size);
}

5.动态扩容

  • 判断输入的容量是否大于现在数组的长度
  • 扩容1.5倍
  • 创建新数组并复制旧数组中的内容
private void expandCapacity(int needCapacity) {
    int oldCapacity = elements.length;
    if (oldCapacity >= needCapacity) {
        return;
    }
    int newCapacity = (oldCapacity >> 1) + oldCapacity;
    Object[] newElements = new Object[newCapacity];
    for (int i = 0; i < size; i++) {
        newElements[i] = elements[i];
    }
    elements = newElements;
    System.out.println(oldCapacity+"扩容为 " + newCapacity);
}

6.详细代码

package 数据结构和算法.数据结构.list.array;

import 数据结构和算法.数据结构.list.AbstractList;
import 数据结构和算法.数据结构.list.List;


/**
 * @author likeLove
 * @since 2020-09-29  20:49
 */
public class ArrayList<T> extends AbstractList<T> implements List<T> {
    /**
     * 当前数组元素个数
     */
    private int size;

    /**
     * 存放元素的数组
     */
    private T[] elements;

    /**
     * 默认数组大小
     */
    public static final int DEFAULT_CAPACITY = 10;

    /**
     * 初始化数组大小
     *
     * @param capacity 初始化容量
     */
    public ArrayList(int capacity) {
        //如果传入的数组容量大小  小于  默认的 10,就直接初始化为10
        capacity = Math.max(capacity, DEFAULT_CAPACITY);
        elements = (T[]) new Object[capacity];
    }

    public ArrayList() {
        //如果不传入初始化数组容量
        this(DEFAULT_CAPACITY);
    }


    /**
     * 查找元素在数组中的位置
     *
     * @param o 需要查找的元素
     *
     * @return 元素在数组中的索引
     */
    @Override
    public int indexOf(T o) {
        // 循环遍历,判断 o 是否等于数组中对应的元素
        for (int i = 0; i < size; i++) {
            if (elements[i].equals(o)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 添加元素到数组的最后
     *
     * @param o 需要添加的元素
     */
    @Override
    public void add(T o) {
        //  调用add
        add(size, o);
    }

    /**
     * 添加元素到数组的指定位置
     *
     * @param index 指定位置
     * @param o     元素
     */
    @Override
    public void add(int index, T o) {
        if (o == null) return;
        checkIndexOfAdd(index);
        // likelove: 2020/10/1  动态扩容
        expandCapacity(size + 1);
        for (int i = size; i > index; i--) {
            elements[i + 1] = elements[i];
        }
        elements[index] = o;
        size++;
    }


    /**
     * 移除指定位置的元素
     *
     * @param index 指定位置
     *
     * @return 被移除的元素
     */
    @Override
    public T remove(int index) {
        checkIndex(index);
        T remove = elements[index];
        for (int i = index; i < size; i++) {
            elements[i] = elements[i + 1];
        }
        elements[size] = null;
        size--;
        return remove;
    }

    /**
     * 移除指定元素
     *
     * @param o o
     *
     * @return 被移除的元素
     */
    @Override
    public T remove(T o) {
        if (o == null) return null;
        int index = indexOf(o);
        return remove(index);
    }

    /**
     * 根据索引返回元素(从0开始)
     *
     * @param index 元素的索引
     *
     * @return 元素
     */
    @Override
    public T get(int index) {
        //判断字符是否在正常范围之内
        checkIndex(index);
        return elements[index];
    }


    /**
     * 为索引位置设置新的元素
     *
     * @param index 索引
     * @param o     新元素
     *
     * @return 旧元素
     */
    @Override
    public T set(int index, T o) {
        // 检查index是否合法
        checkIndex(index);
        //取出原有的元素
        T old = elements[index];
        elements[index] = o;
        return old;
    }

    /**
     * 清空数组
     */
    @Override
    public void clear() {
        elements = (T[]) new Object[elements.length];
        size = 0;
    }

    /**
     * 动态扩容
     *
     * @param needCapacity 需要的容量
     */
    private void expandCapacity(int needCapacity) {
        int oldCapacity = elements.length;
        if (oldCapacity >= needCapacity) {
            return;
        }
        int newCapacity = (oldCapacity >> 1) + oldCapacity;
        Object[] newElements = new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newElements[i] = elements[i];
        }
        elements = (T[]) newElements;
        System.out.println(oldCapacity + "扩容为 " + newCapacity);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb./*append("size = ").append(size).*/append("[");
        for (int i = 0; i < size; i++) {
            sb.append(elements[i]);
            if (i < size - 1) {
                sb.append(",").append(" ");
            }
        }
        sb.append("]");
        return String.valueOf(sb);
    }
}

7.抽取List接口

package 数据结构和算法.数据结构.list;

/**
 * @author likeLove
 * @since 2020-09-29  20:54
 * List的接口设计
 */
public interface List<T> {
    /**
     * 获取数组元素个数
     *
     * @return 当前数组元素个数
     */
    int size();


    /**
     * 判断元素是否存在
     *
     * @param o 元素
     *
     * @return 返回这个元素是否存在
     */
    boolean contains(T o);

    /**
     * 判断数组是否为空
     *
     * @return 数组是否为空
     */
    boolean isEmpty();

    /**
     * 查找元素在数组中的位置
     *
     * @param o 需要查找的元素
     *
     * @return 元素在数组中的索引
     */
    int indexOf(T o);

    /**
     * 添加元素到数组
     *
     * @param o 需要添加的元素
     */
    void add(T o);

    /**
     * 添加元素到数组的指定位置
     *
     * @param index 指定位置
     * @param o     元素
     */
    void add(int index, T o);

    /**
     * 移除指定位置的元素
     *
     * @param index 指定位置
     *
     * @return 被移除的元素
     */
    T remove(int index);

    /**
     * 移除指定元素
     * @param o o
     * @return 被移除的元素
     */
    T remove(T o);

    /**
     * 根据索引返回元素(从0开始)
     *
     * @param index 元素的索引
     *
     * @return 元素
     */
    T get(int index);

    /**
     * 为索引位置设置新的元素
     *
     * @param index 索引
     * @param o     新元素
     *
     * @return 旧元素
     */
    T set(int index, T o);

    /**
     * 清空数组
     */
    void clear();
}

8.抽取AbstractList抽象类

package 数据结构和算法.数据结构.list;

/**
 * @author likeLove
 * @since 2020-10-01  15:14
 */
public abstract class AbstractList<T> implements List<T> {
    /**
     * 当前数组元素个数
     */
    protected int size;

    /**
     * 获取数组元素个数
     *
     * @return 当前数组元素个数
     */
    @Override
    public int size() {
        return size;
    }

    /**
     * 判断元素是否存在
     *
     * @param o 元素
     *
     * @return 返回这个元素是否存在
     */
    @Override
    public boolean contains(T o) {
        //查找这个元素的索引,如果返回的索引 > 0,就表示这个元素不存在
        return indexOf(o) >= 0;
    }

    /**
     * 判断数组是否为空
     *
     * @return 数组是否为空
     */
    @Override
    public boolean isEmpty() {
        //如果数组大小 == 0 就表示数组为空
        return size == 0;
    }

    /**
     * 检查索引是否越界
     *
     * @param index 索引
     */
    protected void checkIndex(int index) {
        if (index < 0 || index >= size) {
            outOfBoundsException(index);
        }
    }

    /**
     * 检查索引是否越界(仅限添加方法)
     *
     * @param index 索引
     */
    protected void checkIndexOfAdd(int index) {
        if (index < 0 || index > size) {
            outOfBoundsException(index);
        }
    }

    /**
     * 抛出数组越界异常
     *
     * @param index 索引
     */
    protected void outOfBoundsException(int index) {
        throw new IndexOutOfBoundsException("index = " + index + "," + "size = " + size);
    }
}

9.动态缩容

/**
 * Trim capacity. 动态缩容
 * 不需要缩容的情况:
 * 1.实用的空间超过总容量的一半
 * 2.使用的空间小于默认的容量
 * 
 * size:已经使用的容量
 * capacity:总容量
 */
private void trimCapacity() {
    int oldCapacity = elements.length;
    int newCapacity = (oldCapacity >> 1) ;
    if (size >= newCapacity || oldCapacity <= DEFAULT_CAPACITY) {
        return;
    }

    //缩容
    Object[] newElements = new Object[newCapacity ];
    for (int i = 0; i < size; i++) {
        newElements[i] = elements[i];
    }

    //引用
    elements = (T[]) newElements;
    System.out.println(oldCapacity + "缩容 " + newCapacity);
}
posted @ 2020-10-05 20:49  likelovecode  阅读(107)  评论(0)    收藏  举报