Подтвердить что ты не робот

Как представить нулевой примитивный тип int в Java?

Я проектирую класс сущности, у которого есть поле с именем "documentYear", которое может иметь беззнаковые целочисленные значения, такие как 1999, 2006 и т.д. Между тем это поле также может быть "неизвестным", то есть не уверен, какой год документ создается.

Следовательно, нулевой тип int, как в С#, будет хорошо подходить. Тем не менее, Java не имеет нулевой возможности, как у С#.

У меня есть два варианта, но мне они не нравятся:

  • Используйте java.lang.Integer вместо примитивного типа int;
  • Используйте -1 для представления "неизвестного" значения

Есть ли у кого-то лучшие варианты или идеи?

Обновить. Мой класс объектов будет иметь десятки тысяч экземпляров; поэтому накладные расходы на java.lang.Integer могут быть слишком тяжелыми для общей производительности системы.

4b9b3361

Ответ 1

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

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

Ответ 2

Использование класса Integer здесь, вероятно, то, что вы хотите сделать. Накладные расходы, связанные с объектом, скорее всего (хотя и не обязательно) тривиальны для вашей реакции на общую реакцию и производительность.

Ответ 3

Десятки тысяч экземпляров Integer не много. Подумайте о том, чтобы расходовать несколько сотен килобайт, а не оптимизировать преждевременно. Это небольшая цена, чтобы заплатить за правильность.

Остерегайтесь использования дозорных значений, таких как null или 0. Это в основном составляет ложь, поскольку 0 не год, а null не является целым числом. Общим источником ошибок, особенно если вы в какой-то момент не являетесь единственным разработчиком программного обеспечения.

Считайте использование нулевого типа типа null, например Option, иногда называемого Maybe. Популярно в таких языках, как Scala и Haskell, это похоже на контейнер с одним или нулевым элементом. Ваше поле будет иметь тип Option<Integer>, который рекламирует необязательный характер вашего поля года для системы типов и заставляет другой код обрабатывать, возможно, отсутствующие годы.

Здесь находится библиотека, содержащая тип Option.

Вот как вы могли бы называть свой код, если бы вы его использовали:

partyLikeIts.setDocumentYear(Option.some(1999));

Option<Integer> y = doc.getDocumentYear();
if (y.isSome())
   // This doc has a year
else
   // This doc has no year

for (Integer year: y) {
  // This code only executed if the document has a year.
}

Ответ 4

Другим вариантом является наличие связанного флага boolean, который указывает, действительно ли значение года. Этот флаг false означает, что год "неизвестен". Это означает, что вам нужно проверить один примитивный (логический), чтобы узнать, есть ли у вас значение, и если вы это сделаете, проверьте другой примитив (целое число).

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

Ответ 5

Вы можете использовать обычный int, но используйте значение, например Integer.MAX_VALUE или Integer.MIN_VALUE, которые являются константами в качестве недопустимой даты. Также более очевидно, что -1 или низкое отрицательное значение, которое оно недействительно, оно, безусловно, не будет выглядеть как 4-значная дата, которую мы привыкли видеть.

Ответ 6

Если у вас есть целое число и они обеспокоены тем, что произвольное значение null может быть путано с реальным значением, вы можете использовать long вместо этого. Он более эффективен, чем использование Integer и Long.MIN_VALUE не находится рядом с любым допустимым значением int.

Ответ 7

Для полноты другой вариант (определенно не самый эффективный) заключается в использовании класса-оболочки Year.

class Year {
    public int year;
    public Year(int year) { this.year = year; }
}

Year documentYear = null;
documentYear = new Year(2013);

Или, если это более семантично, или вы хотите использовать несколько типов индексируемых ints (кроме Years), вы можете имитировать С# Nullable примитивы следующим образом:

class Int {
    public int value;
    public Int(int value) { this.value = value; }
    @Override 
    public String toString() { return value; }
}

Ответ 8

Использование примитива int по сравнению с типом Integer - прекрасный пример преждевременной оптимизации.

Если вы выполните математику:

  • int = N (4)
  • Целое число = N (16)

Таким образом, для 10 000 ints это будет стоить 40 000 байт или 40 тысяч. Для 10 000 ints это будет стоить 160 000 байт или 160K. Если вы считаете объем памяти, необходимый для обработки изображений/фотографий/видеоданных, которые практически ничтожны.

Мое предложение состоит в том, чтобы прекратить тратить время на преждевременное оптимизацию на основе типов переменных и искать хорошую структуру данных, которая упростит обработку всех этих данных. Независимо от того, что вы делаете, если вы не определяете примитивные переменные 10K по отдельности, это все равно закончится на куче.

Ответ 9

Что случилось с java.lang.Integer? Это разумное решение, если вы не храните очень большие суммы этого значения.

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

PS: Черт бы тебя побрал, я пытался уйти с небольшой белой ложью на объекты против структур. Я хотел сказать, что он использует больше памяти, подобно методу логического флага, хотя синтаксически тип с нулевыми значениями, конечно, лучше. Кроме того, я не был уверен, что кто-то с фоном Java знает, что я имел в виду со структурой.

Ответ 10

java.lang.Integer для этого случая является разумным. И он уже реализовал Serializable, поэтому вы можете сэкономить всего лишь поле года на HDD и загрузить его обратно.

Ответ 11

Другим вариантом может быть использование специального значения внутри (-1 или Integer.MIN_VALUE или подобное), но выведите целое число как два метода:

hasValue() {
    return (internalValue != -1);
}

getValue() {
    if (internalValue == -1) {
        throw new IllegalStateException(
            "Check hasValue() before calling getValue().");
    }
    return internalValue;
}

Ответ 12

Если вы собираетесь экономить память, я предлагаю упаковать несколько лет в одном int. Таким образом, 0 nil. Затем вы можете сделать предположения для оптимизации. Если вы работаете только с текущими датами, например годами 1970-2014 годов, вы можете вычесть 1969 из всех из них и попасть в диапазон 1—55. Такие значения могут быть закодированы только с 6 бит. Таким образом, вы можете разделить свой int, который всегда 32 бит, в 4 зоны, с годом в нем. Таким образом, вы можете упаковать 4 года в диапазоне 1970-2226 в один int. Чем более узкий ваш диапазон, так как только 2000-2014 (4 бит), тем больше лет вы можете упаковать в один int.

Ответ 13

Вы можете использовать @Nullable аннотацию, если использовать java 7