什么时候绝对必要的通用数组 - 一个案例

时间:2015-05-13 14:13:54

标签: java arrays generics arraylist

这个Q是寻找一个绝对必要的通用数组的示例案例。

泛型和数组"不能很好地混合"。

是否有案例 通用ArrayList不会做 - 通用数组没有替代品,必须使用。

Effective Java为通用数组打开了一扇门,表示可能存在需要通用数组的情况。

我一直在使用ArrayList而没有任何缺点,也无法想到这样的情况。

TIA。

注意:我已经看过这些:

与其他一些讨论一起。

8 个答案:

答案 0 :(得分:7)

有些观点:

  • 如果你有一些"遗产"然后,您将被绑定到他们使用的类型。这可能是阵列。

  • 如果您处理本机代码,那么数组将是一种更自然的方式与本机代码交换数据。

  • 如果您访问二进制数据(例如声音文件或类似文件),那么使用数组可以提供帮助。

  • 如果您处理大量二进制数据,那么数组可能会更有效。

因此,有很多理由可以帮助数组(特别是原始类型)。

如果您只处理对象,那么使用List大多数时候都会更容易。

答案 1 :(得分:6)

我想说Bloch意味着方便而不是必要的,数组结构更简单,更容易处理。

作为一种数据结构,从功能的角度来看,ArrayList可与数组互换。

阵列显然更精益内存,但需要额外的努力来获得一些基本功能(即当原始数组不足以容纳新元素时手动数组调整大小)但其他功能已由运行时提供({ {1}}类)。

Arrays由实际ArrayLists数组支持,因此对于搜索和排序等常见操作(使用相同算法时),性能方面没有太大区别。

答案 2 :(得分:3)

一些松散的想法:

array是任何命令式语言(可能是伪装形式)所必需的基本数据类型。如果没有array,我们如何实施ArrayList?:)

但是,我们可以伪装array作为&#34;正常&#34;类型。例如,我们可以引入一个内部lang.lang.Array<E>类型来执行数组操作,并消除Java中的当前array类型。 (忽略原始数组,这是另一个主题)。一切都会好起来的。

然而,我们没有奢侈品来改善&#34;和&#34;清洁&#34;这种语言破坏了向后兼容性。

在引入泛型之前,array可以被视为穷人的泛型。我们无法表达ArrayList<String>,但我们可以String[]。这就是为什么许多旧API返回数组而不是某种集合类型的原因,因为数组更加类型安全。 array甚至是共同变体......等等。

引入泛型之后,array的用例变得更少。通常,您应该避免在公共API中使用数组。 (当然,除了var-arg foo(Bar...),它是引擎盖下的数组)

但是在实现代码中,我们仍然需要 array,它是构建更复杂数据结构的基本数据结构。为此,ArrayList在许多情况下显然更加臃肿。

现在问题是,要实现ArrayList<E>之类的内容,我们应该在内部使用E[]还是Object[]?由于删除,E[]更麻烦 - 俗话说'#34;泛型和数组不能很好地混合&#34;。所以忘记它,只需使用Object[]并在必要时进行演员。

答案 3 :(得分:3)

与数组相比,ArrayList需要少量额外内存。这显然是正确的,因为ArrayList被实现为数组的包装器。根据我的粗略估计,ArrayList将消耗额外的16个字节。

在正常情况下,这没什么好担心的。但是,如果您要创建大量数组(数百万/十亿),它可能会有所作为。

还有原始数组的情况。 ArrayList受集合规则的约束,因此它不能存储原始元素,只能存储相应的对象包装器。因此,例如,byte[]每个元素消耗1个字节,但ArrayList<Byte>每个元素消耗4个字节。如果您的阵列可能非常大,这可能会有所不同。

答案 4 :(得分:3)

通常,ArrayList被认为是more favourable而不是数组。它提供相同的功能,同时更好地集成,尤其是与Java Collection API中的其他类型集成。

因此,使用数组可能会产生特殊要求。一方面,人们可能想要使用需要数组的库(或其他第三方代码)。

另一方面,阵列仍然ArrayList表现更好。我创建了一个Gist,用于比较ArrayList<Integer>int[]的使用情况。 (注意,您不能将{strong>基元与ArrayList一起使用。)创建1.000.000随机元素并在我的机器上找到它们的最大值的平均结果:

Test case CREATE_ARRAY average time: 25.93 ms
Test case CREATE_ARRAY_LIST average time: 44.06 ms
Test case MAX_OVER_ARRAY average time: 1.44 ms
Test case MAX_OVER_ARRAY_LIST average time: 5.86 ms

因此,我们使用ArrayList迂回慢4倍。然而,在普通用例中,这可以安全地被视为微优化。大多数用例要求代码质量高于此类性能改进。

答案 5 :(得分:2)

  

[...]说可能是通用数组的情况   必要的。

似乎约书亚布洛赫只是想要保证安全,即使他不认识一个可能性。

如果作者知道有一个例子,作者为什么会在没有例子的情况下提及这一点?

假设ArrayList将其自身值存储在一个数组中并且只提供有用的方法,这样您就不必重新编写所有内容,我会非常惊讶地面对您可以&#39的情况。 ; t用ArrayList实现某些东西但可以用数组实现。

数据结构本身是相同的,请记住Arrays.asListArrayList.toArray

答案 6 :(得分:1)

泛型是指在数组中使用不同的对象时,或者在保存子实例而不能在循环中进行强制转换时,不需要重写代码。你让类和接口成为其他类的参数。

oracle tutorials

  

消除演员阵容。   以下没有泛型的代码片段需要强制转换:

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
  

当重写使用泛型时,代码不需要转换:

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast

答案 7 :(得分:1)

当我读到这个问题时,我立刻想到了几件事。

一:如果您正在使用Java Micro Edition,则可能没有ArrayList可用。如果你曾经使用遗留代码,这种事情是相当普遍的。与4.0及更高版本(在我看来)相比,.Net 1.1或2.0中的写作感觉就像削减你的手臂一样。 Java Micro Edition类似 - 如果您习惯使用Java 6+,那么J2ME会感觉非常严格。 This question讨论了一下,但我认为我使用常规数组而不是使用向量(根据该线程进行同步...我还没有深入研究过)。

二:如果您使用的是嵌入式系统,需要严格控制阵列的大小。其他答案有点触及了这一点。 IIrc ArrayList的默认功能是在调整大小时将其大小加倍,但我在找到确切的引用时遇到问题。在内存非常有限的嵌入式系统上,如果这样的调整大小试图分配超过系统中的所有内存(例如,你的阵列占用了所有系统内存的75%,调整大小,那么)就不会让我感到惊讶。 ; ll尝试占用150%的内存)。如果您使用数组并手动控制所有调整大小,那么这将成为一个非问题。