Java 结构的数组,还是数组的结构?
嗯,我有一个表,它是我需要存储在Java中的结构数组。天真的不用担心记忆的方法是这样做的:Java 结构的数组,还是数组的结构?,java,data-structures,Java,Data Structures,嗯,我有一个表,它是我需要存储在Java中的结构数组。天真的不用担心记忆的方法是这样做的: public class Record { final private int field1; final private int field2; final private long field3; /* constructor & accessors here */ } List<Record> records = new ArrayList<Record&
public class Record {
final private int field1;
final private int field2;
final private long field3;
/* constructor & accessors here */
}
List<Record> records = new ArrayList<Record>();
编辑:
- 假设记录的#是不经常更改或从不更改的
- 我可能不打算使用OptimizedRecordStore方法,但我想了解存储成本问题,以便能够自信地做出决策
- 显然,如果我在上面的OptimizedRecordStore方法中添加/更改#个记录,我要么用新对象替换整个对象,要么删除“final”关键字
- kd304提出了我脑海中的一个好观点。在与此类似的其他情况下,我需要对记录进行列访问,例如,如果field1和field2是“时间”和“位置”,那么将这些值作为数组用于MATLAB对我来说很重要,这样我就可以高效地绘制/分析它们
如果您真的关心插入/删除性能,那么可能需要不同的数据结构,可能是SortedSet或Map或SortedMap。我也会选择ArrayList版本,因此我不需要担心它的增长。您是否需要具有类似于访问值的列?你的问题背后的情节是什么 编辑您还可以使用通用的
long[][]
矩阵。
我不知道如何将列传递给Matlab,但我猜使用基于列的存储不会获得太多的速度,更有可能会在java计算中降低速度。因为要将int[]字段设置为最终值,所以只能对数组进行一次初始化。因此,如果您想要10^6个field1,Java将需要为每个int[]分隔大量内存,因为您无法重新分配这些数组的大小。对于ArrayList,如果您事先不知道记录的数量,并且可能会删除记录,那么在删除记录之前和之后都会节省大量空间。每当我尝试用Java进行数字运算时,我总是不得不恢复到C风格的编码(即接近您的选项2)。它最大限度地减少了系统中浮动的对象数量,因为您只有3个对象,而不是1000000个对象。我能够使用C风格对实时声音数据进行FFT分析,但使用对象时速度太慢。如何访问数据?如果对字段的访问总是耦合的,那么使用第一个选项,如果您要自己处理字段,那么第二个选项更好 请参阅维基百科上的这篇文章:
关于何时使用单独的数组更方便的一个很好的例子是模拟,其中数字数据被打包在同一个数组中,以及其他属性,如名称、颜色等,这些属性仅用于在其他数组中表示数据。我选择第一种方法(结构数组)除非您访问存储的频率相对较低,并且遇到严重的内存压力问题 第一个版本基本上以“自然”形式存储对象(+1 BTW用于使用不可变记录)。由于每个对象的开销(可能是8-16字节,具体取决于您的JVM),这会占用更多的内存,但非常适合在一个简单的步骤中以方便且人类可以理解的形式访问和返回对象 第二个版本总体上使用更少的内存,但是在每个“get”上分配一个新对象是一个非常难看的解决方案,如果访问频繁,它将无法很好地执行 应考虑的其他一些可能性: 一个有趣的“极端”变体是采用第二个版本,但编写算法/访问方法以直接与底层阵列交互。这显然会导致复杂的相互依赖关系和一些难看的代码,但如果您真的需要,它可能会为您提供绝对最佳的性能。在密集的图形应用程序中使用这种方法是很常见的,例如操纵大量的三维坐标 “混合”选项是将底层数据存储在第二个版本中的数组结构中,但将访问的对象缓存在HashMap中,以便仅在第一次访问特定索引时生成该对象。如果只有一小部分对象可能被访问,但所有数据都需要“以防万一”,这可能是有意义的。(不是直接的答案,而是我认为应该给出的答案) 从你的评论来看 “克莱特斯——我非常尊重你的想法和观点,但你给了我高级编程和软件设计的观点,这不是我想要的
public class OptimizedRecordStore {
final private int[] field1;
final private int[] field2;
final private long[] field3;
Record getRecord(int i) { return new Record(field1[i],field2[i],field3[i]); }
/* constructor and other accessors & methods */
}