Java: установка длины массива для неизвестного количества записей - PullRequest
0 голосов
/ 02 декабря 2009

Я пытаюсь заполнить значения 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. Просто выберите огромный размер для начального массива и надейтесь, что он никогда не переполнится. Недостаток: здесь просят об ошибках массива по индексу.

  5. Или я просто использую append(double d) неправильно?

    private void runAnalysis () создает исключение IllegalArgumentException, IllegalAccessException, InvocationTargetException { Двойной атрибут; weightedAnalysis = новый ArrayRealVector (данные);

    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 ]

4 голосов
/ 02 декабря 2009

RealVector.append () не изменяет вектор, а создает новый вектор: [Java документ RealVector.append ()] (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) время).

Я бы порекомендовал просто использовать java ArrayList<Double> во время построения, а затем просто конвертировать в RealVector или любую другую абстракцию данных, которая вам нравится.

1 голос
/ 02 декабря 2009

Использование RealVector потребует огромного количества памяти и времени на сборку, потому что вам нужно:

RealVector newVector = oldVector.append(d);

append () возвращает вновь созданный объект, который вы хотите для корректности.

Если вы согласны с большими накладными расходами при сборке, взгляните на Apache Commons ArrayUtils , специально добавьте (double) и / или toPrimitive (Double).

1 голос
/ 02 декабря 2009

Я бы предложил 3 как хороший вариант. Использование Double vs double - минимальная проблема, так как была введена автобокс.

1 голос
/ 02 декабря 2009

Почему бы не использовать ArrayList и добавить к нему элементы?

0 голосов
/ 02 декабря 2009

вы можете инициализировать массив, используя

ParseTree.class.getMethods().lenght

как начальная емкость:

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

или лучше

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

это может привести к потере памяти, но это безопасное решение, оно зависит от того, сколько раз попадет в цикл внутри.

если вы предпочитаете, вы можете посчитать, сколько методов аннотировано заранее, а затем выделить точный размер для массива

0 голосов
/ 02 декабря 2009

Вы упомянули, что пытались добавить метод, но на самом деле ничего не добавили. Посмотрев на javadoc, убедитесь, что вы присваиваете результат метода append обратно к исходному значению ... Возможно, вы уже пробовали это, но на всякий случай вы пропустили:

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

другими словами, это не изменит myRealVector:

RealVector myRealVector = new ArrayRealVector(data);
myRealVector.append(1.0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...