Phase2 DAY5 MyArrayList

数组与集合的转换

  • 集合 --> 数组
    Collection: T[] toArray(T[] arr);
  • 数组 --> 集合
    static List asList(T… a) 视图方法
    但是不能增加和删除元素

jdk5特性:
a.泛型
b.自动装箱和自动拆箱
c.静态导入
d.foreach
e.可变长参数

public static void main(String[] args) {
        Integer[] arr = {1, 2, 3, 4, 5};
        List<Integer> list = Arrays.asList(arr); // 视图方法
        System.out.println(list);
        
        添加元素:不可
        list.add(6); // UnsupportedOperationException
  
        
        删除元素:不可
        list.remove(0); // UnsupportedOperationException

        修改元素:可
        list.set(0, 100);
        System.out.println(list);
        System.out.println(Arrays.toString(arr));
    }

数据结构

  • 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
  • 公式:数据结构=数据+结构
  • 数据:用类型表示结构:在任何问题中,数据元素都不是孤立存在的,它们之间都存在着某种关系,这种数据元素相互之间的关系称为结构。
  • 元素之间,通常有以下四种基本结构:
    a.集合:结构中的数据元素之间除了同属于一个集合的关系之外,别无其他关系。这里的集合和数学中集合的概念是一致的。
    b.线性结构:结构中的数据元素之间存在一个对一个的关系。
    c.树形结构图:结构中的数据元素之间存在一个对多个的关系。
    d.网状结构:结构中的数据元素之间,存在多个对多个的关系。

逻辑结构&物理结构

  • 前面分类中定义的关系,描述的是数据元素间的逻辑关系,因此又称为逻辑结构。
  • 但是仅仅知道数据元素间的逻辑关系是不够的,因为我们得实现自己的数据结构。 因此,我们得关注数据结构在计算机底层是如何表示的?
  • 数据结构在计算机中的表示,称为数据的物理结构,又称为存储结构或者映像。

结构的表示可分为两种:顺序存储结构 (顺序映像) 和 链式存储结构 (非顺序映像)。

  • 顺序映像:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。(数组)
  • 非顺序映像:借助指示元素存储地址的”指针”,来表示数据元素的逻辑关系。(链表)

线性表:

  • 顺序映像 (ArrayList)
  • 非顺序映像 (LinkedList)

MyArrayList

为什么在迭代器遍历的时候,用集合的API删除倒数第二个元素不会报异常?
在这里插入图片描述


import com.cskaoyan.exception.ArrayListOverflowException;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyArrayList<E> implements MyList<E> {
    private static final int DEFAULT_CAPACITY = 10;
    private static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
    // 属性
    private Object[] elements;
    private int size;
    private int modCount;//集合结构被修改的次数

    // 构造方法
    public MyArrayList() {
        elements = new Object[DEFAULT_CAPACITY];
    }

    public MyArrayList(int initialCapacity) {
        // 及早失败原则
        if (initialCapacity <= 0 || initialCapacity > MAX_CAPACITY) {
            throw new IllegalArgumentException("initialCapacity=" + initialCapacity);
        }
        elements = new Object[initialCapacity];
    }

    /**
     * 在线性表的末尾添加元素
     *
     * @param e 待添加的元素
     * @return 如果添加成功返回true
     */
    @Override
    public boolean add(E e) {
        add(size, e);
        return true;
    }

    /**
     * 在线性表中指定索引位置添加元素
     *
     * @param index 指定索引位置
     * @param e     待添加的元素
     */
    @Override
    public void add(int index, E e) {
        checkIndexForAdd(index);
        // 判断是否需要扩容
        if (size == elements.length) {
            int minCapacity = size + 1;
            // 计算新数组的大小
            int newCapacity = calculateCapacity(minCapacity);
            // 扩容
            grow(newCapacity);
        }
        // 添加元素
        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];
        }
        elements[index] = e;
        size++;
        modCount++;
    }

    private void grow(int newCapacity) {
        Object[] newArr = new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newArr[i] = elements[i];
        }
        elements = newArr; //Caution!
    }

    private int calculateCapacity(int minCapacity) {
        if (minCapacity > MAX_CAPACITY || minCapacity < 0) {
            throw new ArrayListOverflowException();
        }
        // 一定能够容纳minCapacity个元素
        int newCapacity = elements.length + (elements.length >> 1);
        if (newCapacity > MAX_CAPACITY || newCapacity < 0) {
            newCapacity = MAX_CAPACITY;
        }
        // 返回minCapacity和newCapacity的最大值
        return minCapacity > newCapacity ? minCapacity : newCapacity;
    }

    private void checkIndexForAdd(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("index=" + index + ", size=" + size);
        }
    }

    /**
     * 清空所有元素
     */
    @Override
    public void clear() {
        for (int i = 0; i < size; i++) {
            elements[i] = null;
        }
        size = 0;
        modCount++;
    }

    /**
     * 判断线性表中是否有与指定对象o相等的元素
     *
     * @param o 指定对象
     * @return 如果存在与o相等的元素返回true, 否则返回false.
     */
    @Override
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    /**
     * 获取指定索引位置的元素
     *
     * @param index 指定索引位置
     * @return 该索引位置的元素
     */
    @Override
    @SuppressWarnings("unchecked")
    public E get(int index) {
        checkIndex(index);
        return (E) elements[index];
    }

    private void checkIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index=" + index + ", size=" + size);
        }
    }

    /**
     * 获取线性表中第一个与指定对象o相等元素的索引
     *
     * @param o 指定对象
     * @return 第一个与指定对象o相等元素的索引, 如果线性表中没有这样的元素返回-1
     */
    @Override
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++) {
                if (elements[i] == null) return i;
            }
        } else {
            for (int i = 0; i < size; i++) {
                if (o.equals(elements[i])) return i;
            }
        }
        return -1;
    }

    /**
     * 获取线性表中最后一个与指定对象o相等元素的索引
     *
     * @param o 指定对象
     * @return 最后一个与指定对象o相等元素的索引, 如果线性表中没有这样的元素返回-1
     */
    @Override
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size - 1; i >= 0; i--) {
                if (elements[i] == null) return i;
            }
        } else {
            for (int i = size - 1; i >= 0; i--) {
                if (o.equals(elements[i])) return i;
            }
        }
        return -1;
    }

    /**
     * 判断线性表中是否包含元素
     *
     * @return 如果没有元素, 返回true; 否则返回false
     */
    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 删除指定索引位置的元素
     *
     * @param index 指定索引位置
     * @return 被删除的元素
     */
    @Override
    @SuppressWarnings("unchecked")
    public E remove(int index) {
        checkIndex(index);
        E removeValue = (E) elements[index];
        for (int i = index; i < size - 1; i++) {
            elements[i] = elements[i + 1];
        }
        elements[size - 1] = null;  // 为了避免内存泄漏
        size--;
        modCount++;
        return removeValue;
    }

    /**
     * 删除第一个与指定对象o相等的元素
     *
     * @param o 指定对象
     * @return 如果删除成功返回true, 否则返回false
     */
    @Override
    public boolean remove(Object o) {
        int index = indexOf(o);
        if (index != -1) {
            remove(index);
            return true;
        }
        return false;
    }

    /**
     * 替换指定索引位置的元素
     *
     * @param index 指定索引位置
     * @param e     新值
     * @return 旧值
     */
    @Override
    @SuppressWarnings("unchecked")
    public E set(int index, E e) {
        checkIndex(index);
        E oldValue = (E) elements[index];
        elements[index] = e;
        return oldValue;
    }

    /**
     * 获取线性表中元素的个数
     *
     * @return 性表中元素的个数
     */
    @Override
    public int size() {
        return size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            sb.append(elements[i]).append(", ");
        }
        if (size > 0) sb.delete(sb.length() - 2, sb.length());
        return sb.append("]").toString();
    }

    /**
     * 返回一个迭代器, 光标后面的元素的索引为 0
     *
     * @return 迭代器
     */
    @Override
    public MyIterator<E> iterator() {
        return new Itr();
    }

    /**
     * 返回一个迭代器, 光标后面的元素的索引为 index
     *
     * @param index 光标后面的元素的索引
     * @return 迭代器
     */
    @Override
    public MyIterator<E> iterator(int index) {
        checkIndexForAdd(index);
        return new Itr(index);
    }

    private class Itr implements MyIterator<E> {
        // 属性
        int cursor; // 下一个元素的索引
        int expModCount = modCount;
        int lastRet = -1; // 最近返回元素的索引,-1表示最近没有返回元素, 或者是最近返回的元素失效了

        // 构造方法
        Itr() {

        }

        Itr(int index) {
            cursor = index;
        }

        /**
         * 判断光标后面是否有元素
         *
         * @return 如果光标后面还有元素返回true, 否则返回false
         */
        @Override
        public boolean hasNext() {
            return cursor != size;
        }

        /**
         * 将光标往后移动一个位置, 并将越过的元素返回
         *
         * @return 被光标越过的元素
         */
        @Override
        @SuppressWarnings("unchecked")
        public E next() {
            // 判断迭代器是否失效
            checkConModException();
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            /*E retValue = (E) elements[cursor];
            lastRet = cursor;
            cursor++;
            return retValue;*/
            lastRet = cursor;
            return (E) elements[cursor++];
        }

        private void checkConModException() {
            if (expModCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }

        /**
         * 判断光标前面是否有元素
         *
         * @return 如果光标前面是有元素返回true, 否则返回false
         */
        @Override
        public boolean hasPrevious() {
            return cursor != 0;
        }

        /**
         * 将光标往前移动一个位置, 并把被光标越过的元素返回
         *
         * @return 被光标越过的元素
         */
        @Override
        @SuppressWarnings("unchecked")
        public E previous() {
            checkConModException();
            if (!hasPrevious()) {
                throw new NoSuchElementException();
            }
            /*cursor--;
            E retValue = (E)elements[cursor];
            lastRet = cursor;
            return retValue;*/
            lastRet = --cursor;
            return (E) elements[cursor];
        }

        /**
         * 获取光标后面元素的索引
         *
         * @return 光标后面元素的索引
         */
        @Override
        public int nextIndex() {
            return cursor;
        }

        /**
         * 获取光标前面元素的索引
         *
         * @return 光标前面元素的索引
         */
        @Override
        public int previousIndex() {
            return cursor - 1;
        }

        /**
         * 在光标后面添加元素
         *
         * @param e 待添加的元素
         */
        @Override
        public void add(E e) {
            checkConModException();
            // 如何复用MyArrayList的add(int index, E e)方法呢?
            MyArrayList.this.add(cursor, e);
            expModCount = modCount;
            lastRet = -1;
            cursor++; // 保证插入的顺序与存储的顺序一致
        }

        /**
         * 删除最近返回的元素
         */
        @Override
        public void remove() {
            checkConModException();
            if (lastRet == -1) {
                throw new IllegalStateException();
            }
            MyArrayList.this.remove(lastRet);
            expModCount = modCount;
            // 如何移动cursor呢?
            cursor = lastRet; // Caution!
            lastRet = -1;
        }

        /**
         * 替换最近返回的元素
         *
         * @param e 新值
         */
        @Override
        public void set(E e) {
            checkConModException();
            if (lastRet == -1) {
                throw new IllegalStateException();
            }
            elements[lastRet] = e;
            lastRet = -1;
        }
    }

MyIterator迭代器

import java.util.Iterator;

public interface MyIterator<E> extends Iterator<E> {
    void add(E e);

    boolean hasNext();

    boolean hasPrevious();

    E next();

    int nextIndex();

    E previous();

    int previousIndex();

    void remove();

    void set(E e);
}

MyList链表

public interface MyList<E> extends Iterable<E> {
    boolean add(E e);

    void add(int index, E element);

    void clear();

    boolean contains(Object o);

    E get(int index);

    int indexOf(Object o);

    int lastIndexOf(Object o);

    boolean isEmpty();

    MyIterator<E> iterator();

    MyIterator<E> iterator(int index);

    E remove(int index);

    boolean remove(Object o);

    E set(int index, E element);

    int size();
}

ArrayListOverflowException

public class ArrayListOverflowException extends RuntimeException{
    public ArrayListOverflowException() {
    }

    public ArrayListOverflowException(String message) {
        super(message);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值