2009-12-02 151 views
0

我试图用值填充RealVector(来自Apache Commons Math)。我尝试使用该类的append方法,但实际上并没有增加任何内容。所以现在我使用的是double[],它工作正常,但事先并不知道阵列需要多大。Java:为未知数量的条目设置数组长度

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双重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()); 
        } 
    } 
    

    }

回答

4

RealVector.append()不修改矢量,而是构造新的向量: (http://commons.apache.org/math/apidocs/org/apache/commons/math/linear/RealVector.html#append(double))解释[RealVector.append()的Java文档]:

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构建载体是相当昂贵的操作,如追加()将需要的元素在复制超过(即以您解释的方式构建数组,运行时间为O(n^2)

我会建议在施工过程中使用java的ArrayList<Double>,然后简单地转换为RealVector或任何其他您喜欢的数据抽象。

1

为什么不使用ArrayList并添加元素?

+0

为什么不读书的问题消息,而不是唯一的问题是主体? – BalusC 2009-12-02 17:29:00

+0

他提到使用列表会吃内存。不是解决方案。 – 2009-12-02 17:29:56

0

你提到你尝试了append方法,但实际上并没有添加任何东西。查看javadoc后,确保将append方法的结果分配回原始值...你可能已经尝试过这一点,但以防万一你忽略了:

RealVector myRealVector = new ArrayRealVector(data); 
myRealVector = myRealVector.append(1.0); 

换句话说,这不会改变myRealVector:

RealVector myRealVector = new ArrayRealVector(data); 
myRealVector.append(1.0); 
1

我建议3作为一个不错的选择。自引入Autoboxing以来,使用Double vs double是一个小问题。

1

使用RealVector将承担着巨大的存储量和计算时间来建立量,因为你想要的是:

RealVector newVector = oldVector.append(d); 

的append()返回一个新构造的对象,这是你想要什么样的正确性。

如果您在搭建过程中有很高的开销,请参阅Apache Commons ArrayUtils,特别是添加(double)和/或toPrimitive(Double)。

0

,你可以使用

ParseTree.class.getMethods().lenght 

为初始容量初始化数组:

double[] buf = new double[ ParseTree.class.getMethods().lenght ]; 

或更好

DoubleBuffer buf = DoubleBuffer.allocate([ ParseTree.class.getMethods().lenght); 

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

,如果你愿意,你可以指望有多少方法提前被注释,然后分配的精确的尺寸为数组