[英]Java ArrayList IndexOutOfBoundsException despite giving an initial capacity
[英]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.