这两种方法的不同之处在于将集合转换为数组对象

时间:2015-05-18 12:13:32

标签: java arrays collections

以下两种将集合转换为数组对象的方法的根本区别

 ArrayList<String> iName = new ArrayList<String>();

 String[] array= iName.toArray(new String[iName.size()]);//1
 String[] array= iName.toArray(new String[0]);//2

什么时候应该使用approach-1和何时接近-2?

4 个答案:

答案 0 :(得分:4)

第一种方法更好,因为您创建了一个数组,toArray使用它来存储输入列表的元素。第二种方法导致toArray创建另一个数组,因为它不能在空数组中存储任何内容。

如果将长度大于输入列表大小的数组传递给方法,则会遇到不同的行为,因为在这种情况下,数组的size元素(其中{{ 1}}是输入列表的大小)将被指定为null。

如果在调用方法时没有实例化数组,而是使用预先存在的数组,那么将一个小于列表大小的数组传递给方法是唯一有意义的时间:

size

此处您事先并不知道array = iName.toArray(array); 是否足够大以包含array的元素。如果不是,iName将返回一个新数组。如果是,toArray将返回输入数组。

答案 1 :(得分:2)

这两种方法之间的区别:

    String[] array = iName.toArray(new String[iName.size()]);
    String[] array = iName.toArray(new String[0]);
如果有可能同时修改源集合(在这种情况下为iName),则

完全不同。如果不存在并发的可能性,那么第一行是可取的。

这并不严格适用于您的示例,其中源集合为ArrayList,这不是线程安全的。但是,如果源集合是并发集合,则并发修改下的行为很重要。在这种情况下,第一行具有竞争条件。调用线程首先得到大小;然后,另一个线程可能会添加或删除元素,从而更改其大小。但是调用线程使用大小分配数组并将其传递给toArray

这不会导致错误。如果您仔细阅读Collection.toArray(T[])的规范,则这些案例是明确定义的。如果集合已经增长,将为其分配一个新阵列,使得调用者的阵列分配变得多余。如果集合已缩小,则数组的尾部将以null元素结束。这不一定是错误,但是任何使用结果数组的代码都必须准备好处理空值,这可能会令人不快。

传递零长度数组避免了这些问题,可能会分配无用的零长度数组。 (可以保留一个缓存版本,但它会增加混乱。)如果集合为空,则只返回零长度数组。但是,如果集合具有元素,则集合本身会分配正确大小的数组并填充它。这避免了呼叫者交出一个错误的#34;大小

在Java 8 Streams API中,Stream.toArray方法通过让调用者在数组工厂中传递来避免此问题。这允许调用者指定类型,但允许集合指定适当的大小。尽管如此,这还没有被改装到Collections。这由RFE JDK-8060192涵盖。

答案 2 :(得分:0)

基本上两种方法都做同样的事情,并会产生相同的输出,但在引擎盖下它们的行为有点不同。

在第一种方法中,由于数组的大小足够大,List可以将其项目复制到数组并返回相同的数据。当您使用第二种方法时,List类所做的几乎与您的第一种方法完全相同:创建一个具有正确大小的新数组来复制值。

从效率的角度来看:在第一种方法中,创建一个不使用的阵列,即使创建阵列也不会花费太多时间或处理能力,但这不是一件好事,但它是多余的,不应该这样做。如果您知道列表的大小,所有集合都知道它们的大小,您应该使用第一种方法。

答案 3 :(得分:0)

如果你看一下实现,你可以理解其中的区别:

public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

如果提供的数组小于ArrayList,则会创建一个新数组。如果提供的数组大于ArrayList,它将用于复制列表的后备数组的内容。

就性能而言,最佳做法是使用第一种方法(iName.toArray(new String[iName.size()])),但第二种方法的惩罚并不大(创建0大小的数组)。

我个人使用第二种方法,因为我认为它使代码更具可读性。