I am trying to fill a RealVector (from Apache Commons Math) with values. I tried using the class's append
method, but that didn't actually add anything. So now I'm using a double[]
, which works fine, except I don't know in advance how big the array needs to be.
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);
}
How can I deal with this issue? Here are my ideas:
Iterate through the class and count the methods with the annotation, then use that size to initialize the array. However, this will require an extra loop, and reflection is performance-intensive. (right?)
Pick an arbitrary size for the array, doubling it if space runs out. Downside: requires more lines of code
Use a List<Double>
, then somehow weasel the Double
objects back into doubles
so they can be put in the RealVector
. Uses more memory for the list.
Just pick a huge size for the starting array, and hope that it never overflows. Downside: this is begging for arrayindexoutofbound errors.
Or am I just using append(double d)
wrong?
private void runAnalysis() throws 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()); } }
}
RealVector.append() doesn't modify the vector, but rather constructs a new vector: The [Java doc of RealVector.append()]( http://commons.apache.org/math/apidocs/org/apache/commons/math/linear/RealVector.html#append(double)) explains:
append
RealVector append(double d)
Construct a vector by appending a double to this vector.
Parameters:
d - double to append.
Returns:
a new vector
Please note that using RealVector
to construct the vector is quite an expensive operation, as append() would need to copy the elements over and over (ie constructing the array in the way you explained runs in O(n^2)
time.
I would recommend simply using java's ArrayList<Double>
during construction, and then simply converting to RealVector
or any other data abstraction you like.
为什么不使用ArrayList并向其中添加元素?
I would suggest 3 as a good option. Using Double vs double is a minimal problem since autoboxing was introduced.
Using RealVector will take a huge amount of memory and computation time to build, because what you want is:
RealVector newVector = oldVector.append(d);
append() returns a newly constructed object, which is what you'd want for correctness.
If you're okay with heavy overhead on build, take a look at Apache Commons ArrayUtils , specifically add(double) and/or toPrimitive(Double).
You mentioned that you tried the append method, but that didn't actually add anything. After looking at the javadoc, make sure that you assign the result of the append method back to the original value...You probably already tried this, but just in case you overlooked:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector = myRealVector.append(1.0);
in other words, this won't change myRealVector:
RealVector myRealVector = new ArrayRealVector(data);
myRealVector.append(1.0);
you could initialize the array using the
ParseTree.class.getMethods().lenght
as initial capacity:
double[] buf = new double[ ParseTree.class.getMethods().lenght ];
or better
DoubleBuffer buf = DoubleBuffer.allocate([ ParseTree.class.getMethods().lenght);
this may waste some memory but is a safe solution, it depends on how many hit the if inside the loop has.
if you prefer you may count how many methods are annotated in advance and then allocate the exact size for the array
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.