我最近出现在面试中,面试官问我一个关于Arrays
和ArrayList
的问题。
他问我一个阵列阵列是否可以是多维的,那么为什么ArrayList
的ArrayList
不是多维的?
例如:
// Multidimensional
int[][] array = new int[m][n];
// Not multidimensional
ArrayList<ArrayList<Integer>> seq = new ArrayList<ArrayList<Integer>>();
任何人都可以帮我理解这个吗?
Cay S. Horstmann在他的书“核心Java”中表示不耐烦:
Java中没有二维数组列表,但您可以声明
ArrayList<ArrayList<Integer>>
类型的变量并自行构建行。
由于ArrayList
s可以扩展和缩小而变得锯齿状而不是多维的事实,可以说它不是二维数组,多维意味着固定的行和列,因此我也在注释中说明了Java没有真正的多维数组,但这超出了你的问题的范围。
如果你好奇为什么我说Java没有真正的多维数组有一个读取在the differences between a multidimensional array and an array of arrays in C#?
为了让我的答案更加清楚,Java是否具有真正的多维数组,我没有说java没有多维数组,我说Java没有真正的多维数组,并且期望JLS有声明:
多维数组不需要在每个级别具有相同长度的数组。
出于同样的原因,我把所有备用购物袋放进去的购物袋不是一个多维购物袋。
如果我把一个坚果放在一个袋子里,然后将那个袋子放在另一个袋子里,我必须进行两次操作才能得到坚果。
如果我将螺母放入二维组件托盘中,我可以使用两个索引执行一个操作来访问它:
类似地,列表列表(或数组数组)与真正的二维数组之间存在根本区别 - 采用两个索引的单个操作用于访问二维数组中的元素,两个操作各自采用一个索引用于访问列表列表中的元素。
ArrayList具有单个索引,因此它具有等级1.二维数组具有两个索引,其等级为2。
注意:'二维数组'我不是指数组(引用)的Java数组,而是指其他语言(如FORTRAN)中的二维数组。 Java没有多维数组。如果你的访问者专门提到Java'数组数组'那么我会不同意它们,因为Java的int[][]
定义了一个对整数数组的引用数组,并且需要两个解除引用操作来访问这些元素。例如,C中的数组数组支持使用单个解除引用操作进行访问,因此更接近于多维情况。
我将在这里站出来回答这个问题,但是对于这个广泛的问题没有正确的答案。
我们首先要问,是什么使数组成为多维的?
我将假设你的面试官考虑一个具有固定大小的多维数组(如你在问题中所示),它不能被认为是“锯齿状”。根据微软的说法,C#中的jagged数组如下:
锯齿状阵列的元素可以具有不同的尺寸和大小。
在Java中,多维数组只是一个数组,其中每个元素也是一个数组。必须使用固定大小定义这些数组,以便在其中索引元素,但如上所述,锯齿状数组可以具有不同的大小。
ArrayList
由阵列支持;但是,当向其添加一定数量的元素时,数组会扩展。由于这个原因,ArrayList
可能变得锯齿状,并且可能被认为不再是多维的。
编辑:重读几遍后,我确信你的面试官只是想让你迷惑。老实说,一种数据类型(数组)是多维的,而另一种数据类型(使用数组的ArrayList
)不是多维的。
从另一方面看:它可以像“多维”数组一样使用列表。你只需要用array[row][column]
替换someList.get(row).get(column)
!
最后,java数组以类似的方式实现:两个dim矩阵也只是一个dim数组的一个暗淡数组!换句话说:差异在表面上更多,而不是根深蒂固的概念原因!
而且要非常精确:Java类型系统允许你放下Object[][]
所以在这个意义上,它知道Object[][]
的类型;但正如所说,实际上,没有多维数组;因为Java看到“两个昏暗”的东西作为数组的引用数组!
另一方面:有一个“多维数组”的概念,例如JVM specification明确提到:
multianewarray指令的第一个操作数是要创建的数组类类型的运行时常量池索引。第二个是实际创建的数组类型的维数。 multianewarray指令可用于创建类型的所有维度,如create3DArray的代码所示。请注意,多维数组只是一个对象,因此分别由aload_1和areturn指令加载和返回。
面试官的说法是荒谬的。
正如您在此页面上看到的那样,人们可以争辩说,Java没有真正的多维数组,在这种情况下,它也没有多维数组列表。另一方面,它当然允许您以相同的方式通过数组和ArrayLists表示多维结构。
定义两者之间的主要区别是相当武断和毫无意义的。
可能面试官只是试图开始技术辩论,以测试你解释细节的能力。
ArrayList
是List的实现。这是使用数组实现的List
。数组的使用是一个实现细节。 list interface不支持多维列表的概念,因此你不会期望ArrayList
。此外,它不是作为traditional list data structure的用例。
数组支持多维度,因为它是Java的语言特性。
因为它根本不是维度的。它是一个带有API的对象。任何多维度的外观都是由它的API提供的,但它纯粹是在旁观者眼中。另一方面,阵列是维度的,因此也可以是多维的。