繁体   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