数组列表的数组 vs 数组的数组列表 vs 类似的东西

6
我正在创建一个 TableModel,它将有固定数量的列,但行数将随时间变化而改变(通常会随时间增加)。存储数据的更好方法是什么?
ArrayList[] columns = new ArrayList[numberOfColumns];
// Each array element is one column. Fill each of them with a new ArrayList.
...
public Object getValueAt(int row, int column) {
    return columns[column].get(row);
}

即创建一个ArrayList数组,每个ArrayList表示一列,或者:

ArrayList<Object[]> rows = new ArrayList<Object[]>();
// Each ArrayList element is one row.

public Object getValueAt(int row, int column) {
    return rows.get(row)[column];
}

即创建一个ArrayList,其中包含代表每行的数组。

有什么想法是哪种方法在速度或存储方面更有效?选择1需要在添加每行时扩展N个ArrayList,而选择2只需要扩展一个ArrayList,但还需要创建一个长度为N的新数组(以表示新行)。还是有明显更好的解决方案吗?


好问题。你想让行数和/或列数容易改变吗?此外,你想允许行具有不同长度的列吗?编辑:我的错,我没有完全阅读你问题的第一部分。 - Tom
是的,列数是固定的,但行数是变化的。 - Joonas Pulakka
4个回答

6
如果列的数量是固定的,那么您的数据可能是面向行的,或者至少是行变量,此时每一行应该是一个数组。固定列数意味着您不需要重新分配数组。因此,您的结构应该是:
List<Object[]> rows;

数组元素是一行数据。

但对于你的行对象,有几个选项:

  1. 一个数组;
  2. List或其他Collection;或者
  3. 一个自定义对象。

(3) 可能可以通过使用某种接口来完成,该接口允许您查询列的数量、类型和名称。


谢谢,我认为这是最干净的解决方案。 - Joonas Pulakka
当然,使用对象数组会导致装箱和拆箱数据的放入。这是一个相当大的缺点。 - Jason Short

2
如何使用单个 ArrayList 并像这样访问元素?
public Object getValueAt(int row, int column) { 
    return data.get(row*NUMBER_OF_COLUMNS+column); 
} 

在这种情况下,每个ArrayList对象都是表格中的一个单元格。您不需要任何其他额外的结构。

这可能确实是最有效的选择 - 尽管不是最可读的。 - Joonas Pulakka
我的意思是,例如,删除行需要计算到“data”的正确索引,这需要一些思考,如果搞砸了,整个数据结构就毁了:-) 而且理解代码需要更多的努力-但不是那么多。 - Joonas Pulakka
是的,我明白了。但就像你说的那样,这不是什么大问题。肯定可以做到的。 :) - vpram86
在我看来,将基本上是2D数组的内容压缩成单个维度是一种不必要的微观优化,会牺牲代码的可读性。此外,您必须小心,不要让数据处于不一致的状态。例如,如果您有8列,并且在将第五列添加到后备列表时发生异常。 - cletus
@Joonas:不,这可能并不像你想象的那样高效。就存储而言,有一个“增长因子”(当前大小的x1.5),每当列表需要增加其容量时,它都会影响分配元素的数量。就速度而言,行删除是一场噩梦,列排序则是半夜的噩梦...在这种情况下,我会选择上面的cletus解决方案。 - instcode

1

出于几个原因,我会选择选项#2。

首先,数组具有固定长度,而ArrayList是灵活的。考虑到您的#columns是固定的,因此每行都有一个数组似乎很自然。

选项#1很危险,因为它会产生隐含的要求,即所有ArrayList的长度都相同。您可能会意外地忽略其中任何一个,从而创建错误。在选项#2中,您不会遇到这个问题。

最后,似乎常见的惯例是先索引行,然后再索引列。


1
个人而言,我会选择一个固定长度数组的ArrayList。如果你要处理大量的行,这可能比分配一堆ArrayList更节省空间(也许更快),因为它最初由长度为10的数组支持。因此,如果您的列少于10个,您将浪费空间。另一方面,如果您有更多列,则添加其他列时ArrayList将不得不调整其支持数组的大小。
编辑:实际上,您可以在ArrayList的构造函数中设置容量,所以我想这可能没有太大区别: http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接