zoukankan      html  css  js  c++  java
  • 常见面试题之自我实现ArrayList & LinkedList

    面试者经常遇到集合类源码的问题。我们不求将所有的细节都记住,但ArrayList与LinkedList比较、add、get、remove、扩容、及相关时间复杂度等核心思想要说得一清二楚。

    ArrayList底层用数组实现,可以快速访问某一节点的值,但插入删除会调用System.arraycopy方法,数组容量不够时需进行扩容,扩容采用新的大数组取代旧的数组。

    public class MyArrayList<E> {
    
      private Object[] elementData;
    
      public int size;// 数组中元素长度
    
      private static final int INITIAL_CAPACITY = 10;// 初始容量
    
      public MyArrayList() {
        elementData = new Object[INITIAL_CAPACITY];
      }
    
      public MyArrayList(int capacity) {
        elementData = new Object[capacity];
      }
    
      private void ensureCapacity(int minCapacity) {
        int oldCapacity = elementData.length;
        if (minCapacity > oldCapacity) {
          int newCapacity = (oldCapacity * 3) / 2 + 1;
          if (newCapacity < minCapacity)
            newCapacity = minCapacity;
          elementData = Arrays.copyOf(elementData, newCapacity);// 扩容调用Arrays.copyOf方法 将容量扩为原数组长度的3/2, 现有的数组引用指向了新的数组
                                          // 时间复杂度为O(n)
        }
      }
    
      // 在數組末尾添加元素 時間複雜度O(1)
      public void add(E e) {
      if (e == null)
        return;
      ensureCapacity(size + 1);
      elementData[size++] = e;
      }
    
      public void add(E e, int index) {
        if (e == null || index > size || index < 0)
          return;
        ensureCapacity(size + 1);
        System.arraycopy(elementData, index, elementData, index + 1, size - index);  // 数组中间添加元素
                                                  //平均时间复杂度O(n)
                    
        elementData[index] = e;
        size++;
      }
    
      public E get(int index) {
        if (index > size || index < 0)
          return null;
        return (E) elementData[index]; // 按位置获取元素 时间复杂度为O(1)public class MyArrayList<E> {
    
      private Object[] elementData;
    
      public int size;// 数组中元素长度
    
      private static final int INITIAL_CAPACITY = 10;// 初始容量
    
      public MyArrayList() {
        elementData = new Object[INITIAL_CAPACITY];
      }
    
      public MyArrayList(int capacity) {
        elementData = new Object[capacity];
      }
    
      private void ensureCapacity(int minCapacity) {
        int oldCapacity = elementData.length;
        if (minCapacity > oldCapacity) {
          int newCapacity = (oldCapacity * 3) / 2 + 1;
          if (newCapacity < minCapacity)
            newCapacity = minCapacity;
          elementData = Arrays.copyOf(elementData, newCapacity);// 扩容调用Arrays.copyOf方法 将容量扩为原数组长度的3/2, 现有的数组引用指向了新的数组
                                          // 时间复杂度为O(n)
        }
      }
    
      // 在數組末尾添加元素 時間複雜度O(1)
      public void add(E e) {
      if (e == null)
        return;
      ensureCapacity(size + 1);
      elementData[size++] = e;
      }
    
      public void add(E e, int index) {
        if (e == null || index > size || index < 0)
          return;
        ensureCapacity(size + 1);
        System.arraycopy(elementData, index, elementData, index + 1, size - index);  // 数组中间添加元素
                                                  //平均时间复杂度O(n)
                    
        elementData[index] = e;
        size++;
      }
    
      public E get(int index) {
        if (index > size || index < 0)
          return null;
        return (E) elementData[index]; // 按位置获取元素 时间复杂度为O(1)
      }
    
      public E remove(int index) {
        if (index > size || index < 0)
          return null;
        E oldValue = get(index);
        int numMoved = size - index - 1;
        if (numMoved > 0) // 删除元素 平均复杂度为O(n)
          System.arraycopy(elementData, index + 1, elementData, index,
                  numMoved);
        elementData[--size] = null;
        return oldValue;
      }
    }
      }
    
      public E remove(int index) {
        if (index > size || index < 0)
          return null;
        E oldValue = get(index);
        int numMoved = size - index - 1;
        if (numMoved > 0) // 删除元素 平均复杂度为O(n)
          System.arraycopy(elementData, index + 1, elementData, index,
                  numMoved);
        elementData[--size] = null;
        return oldValue;
      }
    }

    可见,ArrayList可以根据索引快速访问任意元素,但插入、删除、扩容操作会调用System.arrayCopy()方法,这是个非常占用系统资源的操作。当你遇到访问元素比插入或者是删除元素更加频繁的时候,你应该使用ArrayList,在频繁的插入或者是删除元素的情况下,LinkedList的性能会更加好一些。

  • 相关阅读:
    Linux学习进阶路线图
    Ubuntu打开终端的方法三种
    Linux下显示IP地理位置信息的小工具-nali
    kail2 linux 安装vmware tools
    Ubuntu下apt-get命令详解
    Eclipse安卓开发环境
    纪念逝去的计算器之计算表达式结果
    今年暑假要AC
    结课博客作业
    第七次课程作业
  • 原文地址:https://www.cnblogs.com/leeqq/p/3940086.html
Copyright © 2011-2022 走看看