繁体   English   中英

Java:为未知数量的条目设置数组长度

[英]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);
}

我该如何处理? 这是我的想法:

  1. 遍历该类并使用批注对方法进行计数,然后使用该大小初始化数组。 但是,这将需要一个额外的循环,并且反射是性能密集的。 (对?)

  2. 为数组选择任意大小,如果空间用完,则将其加倍。 缺点:需要更多代码行

  3. 使用List<Double> ,然后以某种方式将Double对象RealVectordoubles以便可以将它们放入RealVector 为列表使用更多的内存。

  4. 只需为起始数组选择一个很大的大小,并希望它永远不会溢出。 缺点:这是在请求arrayindexoutofbound错误。

  5. 还是我只是使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM