[英]Java: Setting array length for an unknown number of entries
我正在尝试用值填充RealVector (来自Apache Commons Math)。 我尝试使用该类的append
方法,但实际上并没有添加任何内容。 因此,现在我使用的是double[]
,它工作正常,但我事先不知道数组需要多大。
private void runAnalysis() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Double attr;
double[] data = new double[100]; // TODO: bad.
int i = 0;
for (Method m : ParseTree.class.getMethods()) {
if (m.isAnnotationPresent(Analyze.class)) {
attr = (Double) m.invoke(this);
analysis.put(m.getAnnotation(Analyze.class).name(), attr);
data[i++] = attr * m.getAnnotation(Analyze.class).weight();
}
}
weightedAnalysis = new ArrayRealVector(data);
}
我该如何处理? 这是我的想法:
遍历该类并使用批注对方法进行计数,然后使用该大小初始化数组。 但是,这将需要一个额外的循环,并且反射是性能密集的。 (对?)
为数组选择任意大小,如果空间用完,则将其加倍。 缺点:需要更多代码行
使用List<Double>
,然后以某种方式将Double
对象RealVector
为doubles
以便可以将它们放入RealVector
。 为列表使用更多的内存。
只需为起始数组选择一个很大的大小,并希望它永远不会溢出。 缺点:这是在请求arrayindexoutofbound错误。
还是我只是使用append(double d)
错误?
私有无效runAnalysis()抛出IllegalArgumentException,IllegalAccessException,InvocationTargetException {Double attr; weightedAnalysis =新的ArrayRealVector(data);
for (Method m : ParseTree.class.getMethods()) { if (m.isAnnotationPresent(Analyze.class)) { attr = (Double) m.invoke(this); analysis.put(m.getAnnotation(Analyze.class).name(), attr); weightedAnalysis.append(attr * m.getAnnotation(Analyze.class).weight()); } }
}
RealVector.append()不会修改矢量,而是构造一个新的矢量:[RealVector.append()的Java文档]( http://commons.apache.org/math/apidocs/org/apache/commons /math/linear/RealVector.html#append(double))解释:
append
RealVector append(double d)
Construct a vector by appending a double to this vector.
Parameters:
d - double to append.
Returns:
a new vector
请注意,使用RealVector
构造向量是一个非常昂贵的操作,因为append()将需要一遍又一遍地复制元素(即,按照您解释的方式在O(n^2)
时间内构造数组O(n^2)
。
我建议仅在构造过程中使用java的ArrayList<Double>
,然后简单地转换为RealVector
或您喜欢的任何其他数据抽象。
为什么不使用ArrayList并向其中添加元素?
我建议将3作为一个不错的选择。 由于引入了自动装箱,因此使用Double vs Double是一个最小的问题。
使用RealVector会花费大量的内存和计算时间,因为您想要的是:
RealVector newVector = oldVector.append(d);
append()返回一个新构造的对象,这就是您想要的正确性。
如果您可以在构建上承担大量开销,可以看看Apache Commons ArrayUtils ,特别是add(double)和/或toPrimitive(Double)。
您提到您尝试了append方法,但实际上并没有添加任何内容。 查看完Javadoc之后,请确保将append方法的结果分配回原始值...您可能已经尝试过此操作,但以防万一您忽略了:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector = myRealVector.append(1.0);
换句话说,这不会更改myRealVector:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector.append(1.0);
您可以使用来初始化数组
ParseTree.class.getMethods().lenght
作为初始容量:
double[] buf = new double[ ParseTree.class.getMethods().lenght ];
或更好
DoubleBuffer buf = DoubleBuffer.allocate([ ParseTree.class.getMethods().lenght);
这可能会浪费一些内存,但这是一个安全的解决方案,它取决于循环中是否命中了多少个。
如果愿意,可以预先计算要注释的方法数量,然后为数组分配确切的大小
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.