Можно ли хранить null в стандартных коллекциях?
Все интерфейсы Collections Framework позволяют своим реализациям самостоятельно решать, поддерживать ли null-значения. Если реализация не может принять null, она выбрасывает NullPointerException или ClassCastException.
Большинство списков (LinkedList, ArrayList) принимают null без проблем. Большинство очередей (Queue и Deque) не хранят null – возвращая из читающего метода null они сообщают пользователю о пустоте коллекции.
Unmodifiable Maps не допускают null-ов совсем. Обычные изменяемые мапы обычно не испытывают трудности со значениями null. А вот с ключами дело обстоит интереснее.
HashMap не может посчитать hash-сумму от null. Но вместо этого для таких ключей просто используется бакет номер 0.
Иногда этот вопрос дается как задача с подвохом про TreeMap. Nullability её ключей зависит от готовности к этому компаратора. Натуральный порядок (который работает для Comparable ключей) не поддерживает null. Раньше в реализации был баг, который позволял положить значение по ключу null в корень дерева без выброса исключения.
Для значений Set-ов действуют те же правила, что для ключей лежащих в основе их Map-ов.
Java Guru🤓 #java
Все интерфейсы Collections Framework позволяют своим реализациям самостоятельно решать, поддерживать ли null-значения. Если реализация не может принять null, она выбрасывает NullPointerException или ClassCastException.
Большинство списков (LinkedList, ArrayList) принимают null без проблем. Большинство очередей (Queue и Deque) не хранят null – возвращая из читающего метода null они сообщают пользователю о пустоте коллекции.
Unmodifiable Maps не допускают null-ов совсем. Обычные изменяемые мапы обычно не испытывают трудности со значениями null. А вот с ключами дело обстоит интереснее.
HashMap не может посчитать hash-сумму от null. Но вместо этого для таких ключей просто используется бакет номер 0.
Иногда этот вопрос дается как задача с подвохом про TreeMap. Nullability её ключей зависит от готовности к этому компаратора. Натуральный порядок (который работает для Comparable ключей) не поддерживает null. Раньше в реализации был баг, который позволял положить значение по ключу null в корень дерева без выброса исключения.
Для значений Set-ов действуют те же правила, что для ключей лежащих в основе их Map-ов.
Java Guru🤓 #java
👍15🔥5❤3
Приглашаем на открытый урок.
🗓 08 апреля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Java Developer. Professional».
Узнайте, как обеспечить 100% доставку данных в распределенных Java-системах: боремся с потерями, хаосом и scaling-вызовами.
О чём поговорим:
Кому будет интересно:
Вебинар будет полезен разработчикам, архитекторам и специалистам по интеграции, работающим с распределенными системами и стремящимся обеспечить надежную доставку данных.
В результате урока:
Участники научатся выбирать брокеры под задачи, реализовывать паттерны вроде Publisher-Subscriber , а также получат шаблоны кода для интеграции в свои проекты.
🔗 Ссылка на регистрацию: https://vk.cc/cKqwy6
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2🔥2
Какие есть преимущества у массива перед коллекцией?
Для хранения ссылочных типов массив подходит хуже чем ArrayList. В основе реализации коллекции лежит такой же массив, поэтому эффективность будет той же самой. Однако, вам придется самостоятельно реализовывать логику управления хранилищем: например, увеличение массива при переполнении. А значит, будет больше шансов на ошибку.
Если использовать массивы вместо коллекций для примитивов, можно получить выигрыш по эффективности. Коллекции – generic-типы, из-за этого простые значения хранятся в них в форме ссылочных типов-оберток.
1. Autoboxing выделяет память под новый объект, это дорогая операция;
2. Кроме данных, Object занимает дополнительную память под метаинформацию;
3. Ячейки массива лежат близко в оперативной памяти, это увеличивает шансы попадания в кэш процессора.
С другой стороны, для массива всё так же нужно написать больше кода, он сложнее. Поэтому замена листов на массивы обычно считается излишней микрооптимизацией.
Когда сэкономить всё-таки хочется, стоит выбрать одну из множества готовых библиотек не-generic реализаций коллекций. Списки примитивов можно найти в Eclipse Collections. В Android есть HashMap с целочисленными ключами – SparseArray.
Java Guru🤓 #java
Для хранения ссылочных типов массив подходит хуже чем ArrayList. В основе реализации коллекции лежит такой же массив, поэтому эффективность будет той же самой. Однако, вам придется самостоятельно реализовывать логику управления хранилищем: например, увеличение массива при переполнении. А значит, будет больше шансов на ошибку.
Если использовать массивы вместо коллекций для примитивов, можно получить выигрыш по эффективности. Коллекции – generic-типы, из-за этого простые значения хранятся в них в форме ссылочных типов-оберток.
1. Autoboxing выделяет память под новый объект, это дорогая операция;
2. Кроме данных, Object занимает дополнительную память под метаинформацию;
3. Ячейки массива лежат близко в оперативной памяти, это увеличивает шансы попадания в кэш процессора.
С другой стороны, для массива всё так же нужно написать больше кода, он сложнее. Поэтому замена листов на массивы обычно считается излишней микрооптимизацией.
Когда сэкономить всё-таки хочется, стоит выбрать одну из множества готовых библиотек не-generic реализаций коллекций. Списки примитивов можно найти в Eclipse Collections. В Android есть HashMap с целочисленными ключами – SparseArray.
Java Guru🤓 #java
🔥9👍6❤5
9 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot
Реклама. ООО "ШОРТКАТ", ИНН: 9731139396, erid: 2VtzqvtwkJd
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3❤2
Что такое fail-fast и fail-safe итераторы?
Это не какие-то отдельные типы, а характеристики разных реализаций интерфейса Iterator. Они определяют, как поведет себя итератор при изменении перебираемой последовательности.
Fail-fast – «быстрый» итератор. Когда после его создания коллекция как-либо изменилась, он падает с ошибкой без лишних разбирательств. Так работает итератор класса ArrayList, при изменении он выбрасывает ConcurrentModificationException. Рекомендуется не основывать логику программы на fail-fast отказах, и использовать их только как признак ошибки реализации.
Fail-safe – «умный» итератор. Обычно плата за отказоустойчивость – возможная неконсистентность данных («слабая консистентность»). Итератор класса ConcurrentHashMap работает с копией данных, он не выбросит исключение при изменении коллекции, но может не увидеть часть свежих изменений. Плата за отсутствие ошибок других fail-safe итераторов может отличаться, детали всегда можно найти в документации коллекций.
Java Guru🤓 #java
Это не какие-то отдельные типы, а характеристики разных реализаций интерфейса Iterator. Они определяют, как поведет себя итератор при изменении перебираемой последовательности.
Fail-fast – «быстрый» итератор. Когда после его создания коллекция как-либо изменилась, он падает с ошибкой без лишних разбирательств. Так работает итератор класса ArrayList, при изменении он выбрасывает ConcurrentModificationException. Рекомендуется не основывать логику программы на fail-fast отказах, и использовать их только как признак ошибки реализации.
Fail-safe – «умный» итератор. Обычно плата за отказоустойчивость – возможная неконсистентность данных («слабая консистентность»). Итератор класса ConcurrentHashMap работает с копией данных, он не выбросит исключение при изменении коллекции, но может не увидеть часть свежих изменений. Плата за отсутствие ошибок других fail-safe итераторов может отличаться, детали всегда можно найти в документации коллекций.
Java Guru🤓 #java
👍14❤4🔥4
🦾 Тест по Java 🦾
📌Пройдите тест из 20 вопросов и проверьте, насколько вы готовы к обучению на углубленном курсе «Java Developer. Professional» от OTUS.
Сможете сдать - пройдете на курс по спеццене!
👩💻 В программе курса — все актуальные инструменты, необходимые Middle+ разработчику на Java. Возможна рассрочка.
🎁 Начните обучение со скидкой, подробности у менеджеров. ПРОМОКОД: JAVA_04
⏰ Время прохождения теста ограничено 30 минут
👉ПРОЙТИ ТЕСТ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
📌Пройдите тест из 20 вопросов и проверьте, насколько вы готовы к обучению на углубленном курсе «Java Developer. Professional» от OTUS.
Сможете сдать - пройдете на курс по спеццене!
⏰ Время прохождения теста ограничено 30 минут
👉ПРОЙТИ ТЕСТ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2🔥2🥱1
Какая настройка при создании связи Customer-Order приведет к неправильному поведению при сохранении нескольких Order, связанных с одним Customer?
Anonymous Quiz
21%
CascadeType.ALL
15%
fetch = FetchType.EAGER
10%
optional = false
45%
unique = true
10%
referencedColumnName
🔥10👍4❤2
Какие существуют примитивы?
В Java имеется 9 возможных типов значения переменной: ссылка на объект или один из восьми примитивных типов:
🔘 byte – знаковое целое число от -2^7 до 2^7-1;
🔘 short – знаковое целое число от -2^15 до 2^15-1;
🔘 int – знаковое целое число от -2^31 до 2^31-1;
🔘 long – знаковое целое число от -2^63 до 2^63-1;
🔘 float – знаковое число с плавающей точкой 32 бита стандарта IEEE 754;
🔘 double – то же, что и float, но 64 бита;
🔘 char – 16-битный символ Unicode, от '\u0000'(0) до '\uffff'(65535);
🔘 boolean – true или false;
По умолчанию поля примитивных типов принимают нулевые значения: 0, 0L, '\u0000', false. Про особенности работы, способ хранения и специальные значения чисел с плавающей точкой стоит почитать подробнее.
Отдельная интересная тема – boxing/unboxing. Каждый примитивный тип снабжен своей ссылочной версией. Примитивное значение заворачивается и разворачивается из него автоматически при необходимости. Это может приводить к большим затратам на выделение памяти, когда например int индекс цикла используется в качестве значения переменной Object и превращается в Integer без нужды – частая задача на собеседованиях. Еще классы-обертки содержат набор утилитарных методов для их примитивов.
Сколько памяти занимает примитив – вопрос с подвохом. Спецификация требует, чтобы размер был достаточным для всех значений. Конкретный размер определяется реализацией JVM, он может быть больше. Например в 64-bit HotSpot переменная boolean занимает не 1 бит, а 8.
Java Guru🤓 #java
В Java имеется 9 возможных типов значения переменной: ссылка на объект или один из восьми примитивных типов:
По умолчанию поля примитивных типов принимают нулевые значения: 0, 0L, '\u0000', false. Про особенности работы, способ хранения и специальные значения чисел с плавающей точкой стоит почитать подробнее.
Отдельная интересная тема – boxing/unboxing. Каждый примитивный тип снабжен своей ссылочной версией. Примитивное значение заворачивается и разворачивается из него автоматически при необходимости. Это может приводить к большим затратам на выделение памяти, когда например int индекс цикла используется в качестве значения переменной Object и превращается в Integer без нужды – частая задача на собеседованиях. Еще классы-обертки содержат набор утилитарных методов для их примитивов.
Сколько памяти занимает примитив – вопрос с подвохом. Спецификация требует, чтобы размер был достаточным для всех значений. Конкретный размер определяется реализацией JVM, он может быть больше. Например в 64-bit HotSpot переменная boolean занимает не 1 бит, а 8.
Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥5❤3
Сколько объектов станут доступны для сборщика мусора после удаления ссылки на сет?
Anonymous Quiz
13%
0
13%
1
10%
2
21%
3
43%
4
👍13🔥6
Что такое static?
Ключевое слово static используется для объявления вложенных классов, статических методов, полей, блоков инициализации и статических импортов.
Статические поля и методы – члены класса а не экземпляра, потому к ним можно обращаться через имя класса. Код статического блока или метода имеет доступ только к статическим членам. Статические поля не участвуют в сериализации.
Для статических методов используется раннее связывание, то есть вызов конкретного метода разрешается на этапе компиляции, не работают перегрузка и переопределение в наследниках.
Статический блок инициализации выполняется потокобезопасно, один раз сразу после загрузки класса класслоадером. Инициализаторы статических полей выполняются в неявном статическом блоке. Блоков может быть несколько, выполнятся они в порядке объявления.
Статический импорт (static import) импортирует статические члены классов в .java-файл.
Java Guru🤓 #java
Ключевое слово static используется для объявления вложенных классов, статических методов, полей, блоков инициализации и статических импортов.
Статические поля и методы – члены класса а не экземпляра, потому к ним можно обращаться через имя класса. Код статического блока или метода имеет доступ только к статическим членам. Статические поля не участвуют в сериализации.
Для статических методов используется раннее связывание, то есть вызов конкретного метода разрешается на этапе компиляции, не работают перегрузка и переопределение в наследниках.
Статический блок инициализации выполняется потокобезопасно, один раз сразу после загрузки класса класслоадером. Инициализаторы статических полей выполняются в неявном статическом блоке. Блоков может быть несколько, выполнятся они в порядке объявления.
Статический импорт (static import) импортирует статические члены классов в .java-файл.
Java Guru🤓 #java
👍21🔥4❤2
Что будет результатом кода?
Anonymous Quiz
2%
[1, 2, 3, 4, 5, 6]
6%
[2, 4, 6, 8, 10, 12]
6%
[2, 4, 6]
83%
[4, 8, 12]
4%
Ошибка компиляции
👍20🥱13🔥3🌭1
В чем разница между разными модификаторами доступа?
🔘 private – доступ только непосредственно из этого класса и его внутренних/вложенных классов;
🔘 package-private – доступ из всех классов этого пакета. Наследники доступа не имеют. Применяется когда модификатор не указан;
🔘 protected – доступ из всех классов этого пакета и всех наследников;
🔘 public – никаких ограничений доступа;
Модификаторы доступа применяются к классам, интерфейсам, методам и полям. Они нужны для реализации принципа наименьших привилегий и для отделения внутренней реализации от частей публичного API.
Java Guru🤓 #java
Модификаторы доступа применяются к классам, интерфейсам, методам и полям. Они нужны для реализации принципа наименьших привилегий и для отделения внутренней реализации от частей публичного API.
Java Guru🤓 #java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4❤3
👍13🔥6❤4
Опишите процесс создания экземпляра класса
Сначала класс и цепочка его предков должны быть загружены, сверху вниз. Рассмотрим ClassLoader и процесс загрузки классов в будущих постах. Здесь важно сказать, что класс загружается только один раз, при первом к нему обращении в рамках одного класслоадера.
После загрузки каждого класса выделяется память под его статические поля и выполняются статические блоки инициализации. В будущем возможно будет ленивой не только загрузка всего класса, но и инициализация его статических финальных полей.
Далее инстанциируется сам экземпляр. Как и с загрузкой классов, процесс выполняется для всей цепочки наследования, с самого дальнего родителя:
1. Выделяется память в куче для экземпляра, получается ссылка на этот экземпляр;
2. Выполняются инициализации нестатических полей и блоков инициализации в порядке объявления;
3. Вызывается конструктор;
Статические поля интерфейсов не инициализируются при создании объекта, а другого состояния интерфейс не имеет – это исключает вопрос порядка инициализации предков при множественном наследовании.
В процессе конструирования объекта может возникать проблема виртуального вызова в конструкторе, свойственная для многих языков. Effective Java Item 17 рекомендует не использовать переопределяемые методы в расширяемом классе. Иллюстрация неочевидного поведения в результате приведена выше на картинке
Java Guru🤓 #java
Сначала класс и цепочка его предков должны быть загружены, сверху вниз. Рассмотрим ClassLoader и процесс загрузки классов в будущих постах. Здесь важно сказать, что класс загружается только один раз, при первом к нему обращении в рамках одного класслоадера.
После загрузки каждого класса выделяется память под его статические поля и выполняются статические блоки инициализации. В будущем возможно будет ленивой не только загрузка всего класса, но и инициализация его статических финальных полей.
Далее инстанциируется сам экземпляр. Как и с загрузкой классов, процесс выполняется для всей цепочки наследования, с самого дальнего родителя:
1. Выделяется память в куче для экземпляра, получается ссылка на этот экземпляр;
2. Выполняются инициализации нестатических полей и блоков инициализации в порядке объявления;
3. Вызывается конструктор;
Статические поля интерфейсов не инициализируются при создании объекта, а другого состояния интерфейс не имеет – это исключает вопрос порядка инициализации предков при множественном наследовании.
В процессе конструирования объекта может возникать проблема виртуального вызова в конструкторе, свойственная для многих языков. Effective Java Item 17 рекомендует не использовать переопределяемые методы в расширяемом классе. Иллюстрация неочевидного поведения в результате приведена выше на картинке
Java Guru🤓 #java
👍24❤7🔥5