Java 8 ArrayList初始容量是否已损坏?

时间:2016-03-25 15:50:16

标签: java arraylist java-8

今天,当我遇到一个奇怪的问题时,我正在寻找克隆一个ArrayList。 我看了this回答并试了一下。但是,我收到了一个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:Source不适合dest
      在java.util.Collections.copy(Collections.java:556)
      在ArrayListTest2.test(ArrayListTest2.java:13)

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

这对Collections.copy()的文档确实存在问题。其JDK 8 documentation说:

  

目的地列表必须至少与源列表一样长。如果它更长,则目标列表中的其余元素不受影响。

这使用术语&#34; long&#34;并且&#34;更长&#34;这似乎是指列表的长度。但是,如果查看List规范,则没有 length 的定义 - 但 size 的定义和ArrayList中的定义,容量。目前还不清楚Collections.copy()是否根据列表的 size capacity 进行了定义。

事实上,Collections.copy()应根据列表的 size 来定义。 Collections.copy()的{​​{3}}已修改为:

  

目的地列表的大小必须大于或等于源列表的大小。如果它更大,则目标列表中的其余元素不受影响。

ArrayList构造函数的arg设置其初始容量,而不是 size size 是列表中当前存在的元素数。 Collections.copy()要求目标列表的大小更大或更符合源的大小。这就是当您尝试将大小为1的列表复制到大小为0的列表时获得IndexOutOfBoundsException的原因。

答案 1 :(得分:0)

如果目标List太小。我将抛出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);
   }    

答案 2 :(得分:0)

我认为您对initialCapacity的理解存在问题。就像初始化一个充满了&#39; null&#39;在ArrayList的初始化过程中,没有任何事情发生。通过设置initialCapacity n,您所做的就是让编译器知道它应该为n个对象分配足够的内存。请注意,即使已经分配了内存,列表的大小仍为0,因为其中没有元素。

关于copy()。您正尝试将lista复制到初始容量为lista.size() = 0的列表中。那里看起来不舒服吗?

这种混淆可能是因为文档根本没有提到size这个词,但这是关键因素。