我正在尝试用值填充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
个对象重新加入doubles
,以便将它们放入RealVector
。为列表使用更多内存。
只需为起始数组选择一个巨大的大小,并希望它永远不会溢出。缺点:这是在寻找arrayindexoutofbound错误。
或者我只是使用append(double d)
错了?
private void runAnalysis()抛出IllegalArgumentException,IllegalAccessException,InvocationTargetException { Double attr; weightedAnalysis = new 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());
}
}
}
答案 0 :(得分:4)
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()需要反复复制元素(即以{{1}中解释的方式构造数组时间。
我建议在构造期间简单地使用java O(n^2)
,然后简单地转换为ArrayList<Double>
或您喜欢的任何其他数据抽象。
答案 1 :(得分:1)
为什么不使用ArrayList并将元素添加到那个?
答案 2 :(得分:1)
我建议3作为一个不错的选择。使用Double vs double是一个小问题,因为引入了自动装箱。
答案 3 :(得分:1)
使用RealVector将需要大量的内存和计算时间来构建,因为你想要的是:
RealVector newVector = oldVector.append(d);
append()返回一个新构造的对象,这是你想要的正确性。
如果您在构建时花费很多,请查看Apache Commons ArrayUtils,特别是添加(double)和/或toPrimitive(Double)。
答案 4 :(得分:0)
你提到你尝试过append方法,但实际上并没有添加任何内容。查看javadoc之后,请确保将append方法的结果分配回原始值...您可能已经尝试过这个,但以防您忽略了:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector = myRealVector.append(1.0);
换句话说,这不会改变myRealVector:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector.append(1.0);
答案 5 :(得分:0)
您可以使用
初始化数组ParseTree.class.getMethods().lenght
作为初始容量:
double[] buf = new double[ ParseTree.class.getMethods().lenght ];
或更好
DoubleBuffer buf = DoubleBuffer.allocate([ ParseTree.class.getMethods().lenght);
这可能会浪费一些内存,但这是一个安全的解决方案,它取决于循环内部有多少命中。
如果您愿意,可以计算提前注释的方法数量,然后为数组分配确切的大小