數組、List、迭代器


數組

  • 數組創建與初始化

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

    優點:訪問效率高

    缺點:數組長度固定

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

    2. 在創建數組時其類型與數組長度固定(編譯時檢查,這是與其他容器類的不同之處)

    3. 可以使用length查看數組的長度(這是數組唯一可以調用的)

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

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

  • 可變參數列表

    編譯器會把可變參數列表當做數組,所以可以進行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
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM