數組、List、迭代器

數組

  • 數組建立與初始化java

    格式:className[] cn = new className[]{};
    能夠省略{},但必須在[]裏代表長度(變量必須提供維度表達式或數組初始值設定項),能夠不用new,直接使用{}初始化,數組在建立時指定長度後只能一個一個的填充數組,不能使用{ }填充數組數組

    優勢:訪問效率高安全

    缺點:數組長度固定數據結構

    1. 數組在方法內能夠不初始化(自動初始化,例:int-->0)this

    2. 在建立數組時其類型與數組長度固定(編譯時檢查,這是與其餘容器類的不一樣之處)線程

    3. 可使用length查看數組的長度(這是數組惟一能夠調用的)code

    4. 數組能夠持有基本類型,容器的泛型不能夠,可是有自動包裝機制對象

    5. 數組引用指向堆中真實對象,對象中保存其餘對象的引用blog

  • 可變參數列表排序

    編譯器會把可變參數列表當作數組,因此能夠進行foreach,能夠對能夠參數列表傳入數組

  • Arrays

    sort(T[] t); //必須是基本類型或者實現Comparable接口的類型,不然出現異常,基本類型使用快排,引用類型使用穩定歸併
      asList(T... a); //接收的可變參數,返回的是List接口類型的數據,不能強轉爲List的其餘實現類
      fill(); //用指定數據填充整個數組
      binarySearch(); //對已排序的數組查找,使用二分查找
      copyof(); //拷貝數組,底層使用的是 System.arraycopy(): 淺複製: 複製對象的引用, 比for循環快不少, 由於for循環是對對象自己的拷貝(用於ArrayList數組的擴容),   System.arraycopy()方法是native方法, 沒法看到源碼(應該是C/C++實現的)

集合

  • 建立集合時不跟泛型

    編譯器檢查不出元素的類型,取元素時須要強轉,若強轉類型不對則報異常

  • 使用Arrays.asList()生成的List

    進行add()或delet()操做運行時會出異常,由於Arrays.asList()的底層爲數組,長度不可改變

  • 分類

    • Collection

      1. List

        ArrayList LinkedList

      2. set
      3. queue

    • map


List

  • 特色

    1. 容許元素重複
    2. 記錄元素的位置
  • 區別

    ArrayList: 底層數據機構爲數組, 隨機訪問較快, 增刪操做較慢

    LinkedList: 底層數據結構爲鏈表,增刪較快,隨機訪問較慢


ArrayList

  • 隨機訪問元素較快, 不擅長操做插入刪除

  • add(int index, E element) 將指定的元素插入此列表中的指定位置。

    public boolean add(E e) {
          ensureCapacityInternal(size + 1);  // Increments modCount!!
          elementData[size++] = e;
          return true;
      }

    初始化容量: 建立ArrayList時構造器初始化一個空數組, 當使用add()時, 把數組容量變爲靜態字段 DEFAULT_CAPACITY=10

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
          if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              return Math.max(DEFAULT_CAPACITY, minCapacity);
          }
          return minCapacity;
      }
      private void ensureCapacityInternal(int minCapacity) {
          ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
      }
      private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
          // overflow-conscious code
          if (minCapacity - elementData.length > 0)
              grow(minCapacity);
      }

    1.5倍擴容 : 使用System.arraycopy進行擴容,每次擴容oldCapacity >> 1,位運算右移變爲oldCapacity的一半,因此擴容爲原來的1.5倍

    private void grow(int minCapacity) {
          // overflow-conscious code
          int oldCapacity = elementData.length;
          int newCapacity = oldCapacity + (oldCapacity >> 1);
          if (newCapacity - minCapacity < 0)
              newCapacity = minCapacity;
          if (newCapacity - MAX_ARRAY_SIZE > 0)
              newCapacity = hugeCapacity(minCapacity);
          // minCapacity is usually close to size, so this is a win:
          elementData = Arrays.copyOf(elementData, newCapacity);
      }
  • remove() 移除指定數據數-----底層使用System.arraycopy進行數據挪移

  • 線程不安全:
    List list = Collections.synchronizedList(new ArrayList(...));//進行同步

  • 容量大小和元素個數的關係??-----ArrayList裏面有個int size代表當前的元素個數, 每次add元素就會進行size++, 當元素個數等於容量時就會擴容

  • default關鍵字(虛擬擴展方法), 能夠在接口裏對方法實現, List接口實現了sort()方法


迭代器

Iterator

  1. boolean hasNext() 若是仍有元素能夠迭代,則返回 true
  2. E next() 返回迭代的下一個元素
  3. void remove() 從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操做)
  4. default void forEachRemaining(Consumer<? super E> action)

ArrayList迭代器以下

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
  • 不容許在foreach裏刪除或添加(來自< <阿里巴巴java開發手冊> > )

    List<String> a = new ArrayList<>();
      a.add("1");
      a.add("2");
      for (String string : a) {
          if("2".equals(string)) {
              a.remove(string);
          }
          System.out.printlb(String);
      }

    異常: java.util.ConcurrentModificationException

    分析:

    1. remove("1")

      第一輪: cussor=0,size=2,取出"1"後cussor+1,刪除"1"後size=1

      第二輪: cussor=1,size=1, 經hasNext()判斷結束循環,元素"2"沒有獲得遍歷

    2. remove("2")

      第一輪: cussor=0,size=2,取出"1"後cussor+1,size不變

      第二輪: cussor=1,size=2, 取出"2"後cussor+1,刪除"2"後size=1

      第三輪: cussor=2,size=1,hasNext()爲true不能結束循環,此時進入next()方法內的checkForComodification()方法就拋出異常

    解決:

    List<String> list = new ArrayList<>(); 
      list.add("1"); 
      list.add("2"); 
      Iterator<String> iterator = list.iterator(); 
      while (iterator.hasNext()) { 
          String item = iterator.next(); 
          if (item.equals"2") { 
              iterator.remove(); 
          } 
      }

LinkedList

  • LinkedList中的鏈表節點:

    private static class Node<E> {
          E item;
          Node<E> next;
          Node<E> prev;
    
          Node(Node<E> prev, E element, Node<E> next) {
              this.item = element;
              this.next = next;
              this.prev = prev;
          }
      }

  • 方法:

    普通增刪查: LinkedList的相比於ArrayList通常多First和Last方法

    : 後進先出

    push(): 往棧底(列表最後)壓入數據
    
          pop(); 取出棧頂數據(列表開始)
    
          peek()  獲取列表第一個元素,peekFirst   peekLast
    
          poll() 獲取第一個元素並移除改元素 pollFIrst  pollLast

相關文章
相關標籤/搜索