这个Q是寻找一个绝对必要的通用数组的示例案例。
泛型和数组"不能很好地混合"。
是否有案例 通用ArrayList不会做 - 通用数组没有替代品,必须使用。
Effective Java为通用数组打开了一扇门,表示可能存在需要通用数组的情况。
我一直在使用ArrayList而没有任何缺点,也无法想到这样的情况。
TIA。
注意:我已经看过这些:
与其他一些讨论一起。
答案 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.asList
和ArrayList.toArray
答案 6 :(得分:1)
泛型是指在数组中使用不同的对象时,或者在保存子实例而不能在循环中进行强制转换时,不需要重写代码。你让类和接口成为其他类的参数。
消除演员阵容。 以下没有泛型的代码片段需要强制转换:
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%的内存)。如果您使用数组并手动控制所有调整大小,那么这将成为一个非问题。