首頁 >Java >java教程 >[程式碼比較] ArrayList vs Collections.singletonList

[程式碼比較] ArrayList vs Collections.singletonList

WBOY
WBOY原創
2024-08-06 13:20:50423瀏覽

[Code Compare] ArrayList vs Collections.singletonList

我正在啟動一個新執行緒來比較編碼相同功能的不同方法。在這篇文章中,我將比較兩種建立僅包含一個元素的簡單清單的常用方法。具體來說,我將研究最常用的 List 實作建構函式和 Collections.singletonList,這是一個簡單的工廠方法,用於建立包含單一元素的不可變列表。

數組列表

每次初始化 ArrayList 而不指定其初始容量時,它都會以空數組開始。當新增第一個元素時,ArrayList 使用涉及複製陣列的相對複雜的演算法來調整大小。讓我們來看看ArrayList的架構:

  private static final int DEFAULT_CAPACITY = 10;
  private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

  public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  }

  public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
  }

  private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
  }

  private Object[] grow() {
      return grow(size + 1);
  }

  private Object[] grow(int minCapacity) {
    return elementData = Arrays.copyOf(elementData,
                                      newCapacity(minCapacity));
  }

  private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity <= 0) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
  }

以下是逐步發生的事情:

  1. 建立了一個初始空數組 elementData。
  2. 當新增第一個元素時,會將目前大小(為零)與陣列的長度進行比較。
  3. 由於發現其大小為零,因此陣列需要增長以容納新元素。
  4. 呼叫grow方法,計算新的容量。
  5. 新容量最初增加了舊容量的一半,這讓我們有 0 + 0/2 = 0。
  6. 由於newCapacity不足以容納該元素,因此繼續。
  7. 由於發現 elementData 是相同的初始空數組,因此它最終會傳回所需大小 (1) 和 DEFAULT_CAPACTIY (10) 之間的最大值,從而得到大小為 10 的數組。

當您只需要一個始終包含單一元素的簡單清單時,調整大小的過程非常複雜。

也就是說,讓我們來談談我們的替代方案!

集合::singletonList

方法簽名:

公用靜態;列表 singletonList(T o)

描述

此方法傳回一個僅包含指定物件的不可變清單。 Java 1.3引入的singletonList有幾個優點:

  1. 內嵌實作:您可以在一行中使用所需的元素對其進行初始化。
  2. 不變性:讓我們來看看它的實作:

    private static class SingletonList<E> extends AbstractList<E>
        implements RandomAccess, Serializable {
    
      private final E element;
    
      SingletonList(E obj) {
        element = obj;
      }
      ...
    }
    

    SingletonList 繼承自的 AbstractList 定義了所有可變方法,如下所示:

      public boolean add(E e) {
        add(size(), e);
        return true;
      }
    
      public void add(int index, E element) {
        throw new UnsupportedOperationException();
      }
    
      public E remove(int index) {
        throw new UnsupportedOperationException();
      }
    
      public E set(int index, E element) {
          throw new UnsupportedOperationException();
      }
    

    這確保了不可能重複清單的大小或其單一元素的內容。

    不變性是一個非常有利的特性。雖然我不會在這裡深入探討,但有興趣的開發者可以從本文中了解更多。

  3. 記憶體分配: SingletonList 類別僅包含一個簡單欄位來容納單一元素,與ArrayList 不同,ArrayList 使用數組,使用簡單的ArrayList 簡單建構函數,將為我們留下一個數組新增元素後大小為10。

  4. CPU 使用率: SingletonList 建構子接受單一元素作為參數,不需要調整大小、陣列複製或運算。與 ArrayList 添加方法相比,這效率要高得多。

結論

在這篇文章中,我們比較了使用單一元素建立簡單清單的兩種方法:使用 ArrayList 建構子和 Collection.singletonList 方法。雖然 ArrayList 是一種靈活且常用的資料結構,但它會帶來一些不必要的開銷,特別是在添加元素時的記憶體分配和 CPU 使用方面。這一開銷包括調整數組大小和複製數組,這對於僅包含一個元素的列表來說可能是多餘的。但是,如果您需要更改此元素,ArrayList 是一個合適的解決方案。

另一方面,Collection.singletonList 為建立單元素清單提供了更有效的替代方案。這種方法不僅更簡潔、更容易使用,而且保證了不變性,這在許多場景下都是一個顯著的優勢。與 ArrayList 相比,它具有最小的記憶體佔用,幾乎不需要 CPU 資源。

總而言之,對於僅包含一個元素的簡單、不可變列表,Collection.singletonList 因其高效、簡單和不變性而成為更好的選擇。但是,如果您需要修改清單中的元素,ArrayList 可能是更合適的選擇。

在下一篇文章中,我將比較單元素清單的另一種替代方法:List.of 工廠方法。稍後見!

以上是[程式碼比較] ArrayList vs Collections.singletonList的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn