Java, библиотека коллекций Google; проблема с AbstractIterator?

Я использую библиотеку Google Collections AbstractIterator. для реализации генератора. При этом я столкнулся с проблемой; Я сократил его до более простого типа и воспроизвел проблему. Это сокращение явно излишне для того, что оно делает, считая от 1 до numelements через Iterable.

По сути, в следующем коде версия без комментариев работает, а версия с комментариями — нет (предоставляет нулевой элемент последним, вместо того, чтобы заканчиваться последним числом).

Я что-то не так делаю, или это проблема с библиотекой?

private Iterable<Integer> elementGenerator(final int numelements) {
  return new Iterable<Integer>() {
    @Override public Iterator<Integer> iterator() {
      return new AbstractIterator<Integer>(){
        int localcount=0;
        @Override protected Integer computeNext() {
          if (localcount++ == numelements) return endOfData();
          return localcount;
          // return (localcount++ == numelements) ? endOfData() : localcount;
        }
      };
    }
  };
}

Я также пытался возиться с расположением ?: (например, добавляя префикс возврата и вместо этого сравнивая с +1), безрезультатно. Я немного покопался в документации по этому поводу, но ничего не нашел. Очевидно, что синтаксис ?: — это только удобство, а не необходимость, но все же...


person Carl    schedule 30.11.2009    source источник
comment
Версия без комментариев не компилируется. Я так понимаю, вы имеете в виду переключить, какой оператор возврата комментируется, а не просто раскомментировать одну строку?   -  person mR_fr0g    schedule 30.11.2009
comment
Нет, это либо последняя строка комментария, либо две строки до нее.   -  person Andreas Dolk    schedule 30.11.2009
comment
Итератор считает от 1 до (numelements-1) - вместо того, чтобы возвращать numelements, он возвращает endOfData() (но для обеих версий, насколько я могу видеть и воспроизводить @home... magic.)   -  person Andreas Dolk    schedule 30.11.2009
comment
Я не могу не смотреть на этот код и не содрогаться от злоупотребления оператором постинкремента.   -  person Powerlord    schedule 30.11.2009
comment
Он считает от 1 до numelements, так говорит мой тест JUnit. Так и должно быть - значение сравнивается, потом увеличивается. Таким образом, числовые элементы должны быть возвращены последними.   -  person Carl    schedule 30.11.2009
comment
и под этим я подразумеваю, что if (localcount++ == numelements) идентично (localcount == numelements), а затем увеличивает localcount на 1.   -  person Powerlord    schedule 30.11.2009
comment
@R: да, у меня есть грязное белье. Мне также нравится использовать оператор pre-fix, и вы должны увидеть мои злоупотребления в perl. Кроме того, я не чищу зубы после обеда.   -  person Carl    schedule 30.11.2009


Ответы (2)


Вы получаете NullPointerException из-за использования тернарного оператора, условного выражения, с различными числовыми типами. Java имеет сложные правила при смешивании числовых значений разных типов в троичном выражении: ">JLS Section 15.25.

Учитывая, что предполагается, что endOfData() возвращает Integer, а localcount является int, Java распаковывает значение endOfData(). Однако, учитывая, что endOfData() возвращает нуль, операция распаковки приводит к исключению нулевого указателя.

Вы можете либо продолжить использовать оператор if, либо объявить localcount как Integer.

person notnoop    schedule 30.11.2009
comment
Хм; рад, что кто-то более знаком со спецификацией. Сработало как шарм, спасибо. Угадайте, что остается решить проблему с реальной версией. - person Carl; 30.11.2009
comment
Кстати, здесь я рекомендую использовать оператор if. Людям проще не промахнуться в будущих правках. - person notnoop; 30.11.2009
comment
В целом я согласен с тем, что ?: снижает удобочитаемость/сопровождаемость, но когда логика так проста, как в этом случае, и, вероятно, останется таковой, я нахожу однострочный вариант более читаемым. За исключением некоторых всесторонних исследований использования (которые мне было бы интересно увидеть, если они существуют), похоже, предпочтение сводится к простому случаю. - person Carl; 30.11.2009
comment
На самом деле я предпочитаю ?: выражения, поскольку они более компактны. Однако, как вы видели здесь, этот случай не тривиален. В этом случае у вас также есть скрытая сложность распаковки «localcount» в тесте на равенство. - person notnoop; 30.11.2009

Я полагаю, что проблема связана с использованием вами оператора постинкремента в сочетании с тернарным оператором. Помимо этого, два фрагмента должны быть полностью эквивалентны — и вряд ли это вина AbstractIterator, если они не являются таковыми, поскольку ни один из его кодов не вызывается в этот момент.

person Andrzej Doyle    schedule 30.11.2009
comment
Хм.. они возвращают одно и то же. У вас опечатка в последней строке, должно было быть j++, а не i++ - person notnoop; 30.11.2009
comment
Да, я надеялся, что этого никто не видел. Соответственно возвращен пост :$ - person Andrzej Doyle; 30.11.2009