TreeMap.higherEntry возвращает неожиданный нуль - PullRequest
0 голосов
/ 12 ноября 2018

Хорошо, у меня есть этот фрагмент кода, который должен получить случайную запись из взвешенного списка. Тем не менее, когда я пытаюсь вызвать TreeMap.higherEntry, он возвращает ноль, даже если есть более высокая доступная запись. lowerEntry работает, floorEntry возвращает тот же ноль. Вот мой код:

import java.util.*;

public class Randomizer<E> extends ArrayList<E> {
    private Random rng;
    private double defaultWeight;
    public Randomizer(List<E> list) {
        super(list);
        rng = new Random();
        defaultWeight = 1.0d;
    }
    /*Stripped some uninteresting constructor variations for clarity*/
    public void setSeed(long seed) {
        rng.setSeed(seed);
    }
    public E getRandom() {
        TreeMap<Double,E> map = new TreeMap<>();
        double total = 0;
        for(E e : this) {
            if(e instanceof Weighted) {
                map.put(((Weighted) e).getWeight(),e);
                total += ((Weighted) e).getWeight();
            } else {
                map.put(defaultWeight,e);
                total += defaultWeight;
            }
            System.out.println(total);
        }
        double value = rng.nextDouble() * total;
        System.out.println(value + ", " + map.higherKey(value));
        return map.higherEntry(value).getValue();
    }
}

А вот вывод консоли небольшого набора данных:

5.0
9.0
11.0
14.0
15.0
15.5
19.5
22.5
24.0
26.5
27.5
28.0
9.987466924354226, null
Exception in thread "main" java.lang.NullPointerException
    at me.datafox.utils.Randomizer.getRandom(Randomizer.java:52)
    at me.datafox.grick.SwordTest.main(SwordTest.java:39)

Есть ли что-то, что я делаю не так? Набор данных отформатирован очень странным образом, поэтому я его опускаю, но должно быть очевидно, что вычисление итогов по списку весов - это не проблема, с которой я сталкиваюсь.

Ответы [ 4 ]

0 голосов
/ 12 ноября 2018

Ключом для вашей карты должно быть значение total, а не отдельные веса.

    double total = 0;
    for (E e : this) {
        if (e instanceof Weighted) {
            total += ((Weighted) e).getWeight();
        } else {
            total += defaultWeight;
        }
        map.put(total, e);
        System.out.println(total);
    }
    double value = rng.nextDouble() * total;
    double result = map.higherKey(value);
    System.out.println(value + ", " + result);
    return result.getValue();

Например, если у вас есть записи A, B, C с весами 4, 2, 5 соответственно, вы хотите иметь ключи 4, 6, 11. Таким образом, A охватывает 0-4, B охватывает 5-6 и C охватывает 7-11. Я надеюсь, что это объясняет это достаточно.

0 голосов
/ 12 ноября 2018

Отвечая на мой вопрос, чтобы закрыть эту тему. Моя проблема была здесь:

map.put(((Weighted) e).getWeight(),e);
total += ((Weighted) e).getWeight();

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

total += ((Weighted) e).getWeight();
map.put(total,e);
0 голосов
/ 12 ноября 2018

Это не ошибка

public static void main(String[] args) {
  // creating tree map 
  TreeMap<Integer, String> treemap = new TreeMap<Integer, String>();

  // populating tree map
  treemap.put(2, "two");
  treemap.put(1, "one");
  treemap.put(3, "three");
  treemap.put(6, "six");
  treemap.put(5, "five");

  // getting higher key for key 4          
  System.out.println("Checking values of the map");
  System.out.println("Value is: "+ treemap.higherKey(3));
}     

Вывод этого 5

Ваш код делает это:

11 -> getHigherKey = 5

9 -> getHigherKey = null

0 голосов
/ 12 ноября 2018

Javadoc говорит:

Возвращает сопоставление значения ключа, связанное с наименьшим ключом, строго превышающим заданный ключ, или ноль, если такого ключа нет.

Ваш код делает:

double value = rng.nextDouble() * total;

Короче говоря: единственное объяснение состоит в том, что нет такой ценности, отвечающей этим критериям. Другими словами: ваша логика здесь принципиально нарушена.

Дело в том, что вы умножаете случайное значение. Все ставки здесь. Иногда ваш код может привести к ненулевому результату, иногда нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...