Clojure: взаимодействие с Java, почему этот код не работает?

Я закодировал класс, используя Apache Math (что угодно), и у меня есть странный сбой (или, может быть, проблема в моем коде Java?).

вот код

package distributions;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.apache.commons.math3.distribution.AbstractIntegerDistribution;
import org.apache.commons.math3.util.FastMath;

public class CustomDistribution extends AbstractIntegerDistribution {

    long[] v;
    double[] p;
    double[] cp;
    Map<Long, Double> mp = new HashMap<Long, Double>();
    Map<Long, Double> mcp = new HashMap<Long, Double>();

    public CustomDistribution (long[] values, double[] probabilities) {
        v = values;
        p = probabilities;

        int len = values.length;

        for (int i = 0; i < len; i++) {
            mp.put(v[i], p[i]);
        }

        cp = new double[len];
        cp[0] = p[0];
        for (int i = 1; i < len; i++) {
            cp[i] = cp[i-1] + p[i];
        }

        for (int i = 0; i < len; i++) {
            mcp.put(v[i], cp[i]);
        }
    }

      public Map<Long, Double> getMCP () {return mcp;}

    @Override
    public double cumulativeProbability(int v) {
        return mcp.get(v);
    }

    // Not implemented, can be done in Clojure code
    @Override
    public double getNumericalMean() {
        return 0;
    }

    // Not implemented, can be done in Clojure code
    @Override
    public double getNumericalVariance() {
        return 0;
    }

    @Override
    public int getSupportLowerBound() {
        return 0;
    }

    @Override
    public int getSupportUpperBound() {
        return 0;
    }

    @Override
    public boolean isSupportConnected() {
        return false;
    }

    @Override
    public double probability(int v) {
        return mp.get(v);
    }

    // Uses a naive search implementation, should be ok due to data size
    public int sample () {

        double r = FastMath.random();
        int len = p.length;
        Boolean flag = false;
        int i = 0;
        int result = -1;

        while (i < len && flag == false) {
            if (cp[i] < r) {
                i = i + 1;
            }
            else {
                result = (int) v[i];
                flag = true;
            }
        }
        return result;
    }
    }

Обертка Clojure:

(defn create-distribution
  "Creates a distribution from empirical data"
  [data]
  (let [values (long-array (data :values))
        probabilities (double-array (data :probabilities))]
    (CustomDistribution. values probabilities)))

(create-distribution {:values [1 2 3 4] :probabilities [0.3 0.2 0.2 0.3]})

По сути, это дистрибутив с данными внутри в двух формах: HashMaps и Arrays.

В Clojure я пробовал:

(.probability dist 4)
(.probability dist (int 4))

Оба возвращают NullPointerException, NativeMethodAccessorImpl..blabla То же самое для .cumulativeProbabilityMethod (с другой стороны, .sample работает нормально, так что это может быть проблема HashMap)

Я понял, что, возможно, в конструкторе mcp и mp (которые являются HashMaps) не были правильно рассчитаны в конструкторе, но когда я попытался:

(.get (.getMCP dist) 4) 

он возвращает мне правильный результат. Хэш-карта MCP на самом деле является результатом, которого я ожидал.

Так почему же мой код не работает? Мои две строки «функционально» одинаковы. Если я сделал опечатку, я ее не вижу. Может быть, это из-за неизменности?

Спасибо !


person Joseph Yourine    schedule 07.07.2016    source источник


Ответы (1)


Итак, я понял проблему, я забыл, что Java не такая гибкая, как Clojure с числовыми примитивами.

Этот код работает:

@Override
public double cumulativeProbability(int v) {
    return mcp.get((long) v);
}

@Override
public double probability(int v) {
    return mp.get((long) v);
}

В коде Clojure преобразование двойного числа выполняется автоматически. В Java я передал Integer, где HasMap ожидал Long

person Joseph Yourine    schedule 07.07.2016