簡體   English   中英

Java 8 ArrayList 初始容量壞了?

[英]Java 8 ArrayList initial capacity broken?

今天,當我遇到一個奇怪的問題時,我正在考慮克隆一個 ArrayList。 我閱讀了這個答案並嘗試過。 但是,我收到了一個 ArrayOutOfBounds 異常。 所以我仔細研究了一下,似乎 ArrayList<>(int size) 不起作用?
這是一個已知問題嗎?

測試類:

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class ArrayListTest {
    @Test
    public void test() {
        List<String> lista = new ArrayList<>();
        lista.add("a");
        List<String> listb = new ArrayList<>(lista.size());
        System.out.println("Size of lista: " + lista.size());
        System.out.println("Size of listb: " + listb.size());
    }
}

疑難班:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class ArrayListTest2 {
    @Test
    public void test() {
        List<String> lista = new ArrayList<>();
        lista.add("a");
        List<String> listb = new ArrayList<>(lista.size());
        Collections.copy(listb, lista);
        System.out.println("Lista: " + lista);
        System.out.println("Listb: " + listb);
    }
}

結果是:

java.lang.IndexOutOfBoundsException:源不適合目標
在 java.util.Collections.copy(Collections.java:556)
在 ArrayListTest2.test(ArrayListTest2.java:13)

有任何想法嗎?

這確實是Collections.copy()文檔的問題。 它的JDK 8 文檔說:

目標列表必須至少與源列表一樣長。 如果它更長,則目標列表中的其余元素不受影響。

這使用了術語“長”和“更長”,它們似乎指的是列表的長度 但是,如果您查看List規范,則沒有長度的定義——但是有size 的定義,在ArrayList中有容量的定義 目前還不清楚Collections.copy()是根據列表的大小還是容量來定義的。

事實上, Collections.copy()應該根據列表的大小來定義。 Collections.copy()JDK 9 規范已修改為:

目標列表的大小必須大於或等於源列表的大小。 如果它更大,則目標列表中的其余元素不受影響。

ArrayList構造函數的 arg 設置它的初始容量,而不是它的大小 大小是列表中當前存在的元素數。 Collections.copy()要求目標列表的大小大於或等於源的大小。 這就是為什么當您嘗試將大小為 1 的列表復制到大小為 0 的列表時會得到IndexOutOfBoundsException的原因。

如果目標列表太小,我會拋出IndexOutOfBoundsException。

import java.util.*;

public class CollectionsDemo {
   public static void main(String args[]) {
      // create two lists    
      List<String> srclst = new ArrayList<String>(5);
      List<String> destlst = new ArrayList<String>(10);

      // populate two lists
      srclst.add("a");
      srclst.add("b");
      srclst.add("d");

      destlst.add("e");
      destlst.add("f");
      destlst.add("g");


      // copy into dest list
      Collections.copy(destlst, srclst);            

      System.out.println("Value of source list: "+srclst);
      System.out.println("Value of destination list: "+destlst);
   }    

我認為您對initialCapacity的理解存在問題。 就像當你初始化一個用“空”值填充的基元數組時,在ArrayList的初始化過程中不會發生這樣的事情。 通過將initialCapacity設置為n ,您所做的就是讓編譯器知道它應該為n對象分配足夠的內存。 請注意,即使已分配內存,列表的大小仍為 0,因為其中沒有元素。

關於copy() 您正在嘗試將lista復制到初始容量為lista.size() = 0 那里似乎沒有什么不對勁的地方嗎?

這種混淆可能是因為文檔根本沒有提到字size ,但這是這里的關鍵因素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM