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

时间:2009-12-02 17:18:28

标签: java arrays reflection vector

我正在尝试用值填充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个对象重新加入doubles,以便将它们放入RealVector。为列表使用更多内存。

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

  5. 或者我只是使用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());
        }
    }
    

    }

6 个答案:

答案 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);

这可能会浪费一些内存,但这是一个安全的解决方案,它取决于循环内部有多少命中。

如果您愿意,可以计算提前注释的方法数量,然后为数组分配确切的大小