setresizable java что делает
Инструменты пользователя
Инструменты сайта
Содержание
AWT и Swing
В первой версии языка Java для работы с графикой было только библиотека AWT. Эта библиотека – простой набор классов, таких, как Button(кнопка),TextField (текстовое поле), Label (текстовая метка или иконка) и другие.
Вскоре была создана более совершенная библиотека, которую назвали Swing. Она так же включает в себя кнопки,текстовые поля и другие элементы управления графическими приложениями. Названия компонентов этой библиотеке начинается с буквы J. Например JButton, JTextField и т.д.
Работать в Swing лучше, быстрей и удобней.
Основные элементы Swing
Вот некоторые основные объекты, из которых состоят Swing приложения:
Например, можно создать экземпляр класса JPanel и назначить для него схему размещения. Затем создайте различные графические компоненты и добавьте их на панель. После этого добавьте панель на фрейм, задать его размер и сделать его видимым.
JFrame является главным окном для размещения компонентов и представляет их пользователю.
Панель
Панель JPanel — это элемент управления, представляющий собой прямоугольное пространство, на котором можно размещать другие элементы. Элементы добавляются и удаляются методами, унаследованными от класса Container.
У каждой панели есть менеджер размещения, который определяет стратегию взаимного расположения элементов, добавляемых на панель. Его можно изменить методом setLayout(LayoutManager manager).
Оконные элементы управления
Класс JComponent
Все визуальные компоненты библиотеки Swing унаследованы от класса JComponent. Сам этот класс является абстрактными и непосредственно не используется, но все визуальные компоненты наследуют его методы.
Метка JLabel
В большинстве визуальных библиотек метка — один из самых простейших компонентов. Она представляет собой обычный текст, который выводится в заданном месте окна и используется для вывода вспомогательной текстовой информации: подписи к другим элементам, инструкции и предупреждения для пользователя.
Кнопка JButton
Компоненты JToggleButton, JCheckBox, JRadioButton
Компонент JToggleButton представляет собой кнопку, которая может находиться в двух состояниях: нажатом и отпущенном.
Когда пользователь щелкает мышкой по такой кнопке, она изменяет свое состояние. Именно таким образом ведут себя кнопки форматирования на инструментальной панели текстового редактора. Кнопка [I] не только устанавливает или убирает курсивное начертание в выделенном тексте, но и сигнализирует о его наличии или отсутствии.
От класса JToggleButton унаследован класс JCheckBox — флажок.
Этот класс имеет точно такой же набор конструкторов и методов, т.е. не расширяет функциональность предка. Единственное различие между ними — во внешнем виде: JCheckBox выглядит не как кнопка, а как небольшой квадратик, в котором можно поставить или убрать галочку.
Аналогичным образом ведет себя класс JRadioButton — переключатель или радиокнопка, внешне выглядящая как пустой кружок, когда она не выделена и кружок с точкой в выделенном состоянии.
Для того, чтобы элементы объединить в группу, используется специальный контейнер ButtonGroup Если добавить в один такой контейнер несколько элементов JRadioButton, то выбранным всегда будет только один из них.
Текстовое поле JTextField
Для создания текстового поля чаще всего используются конструкторы:
Поле для ввода пароля JPasswordField
JPasswordField является прямым потомком JTextField, поэтому для него справедливо все сказанное выше. JPasswordField является прямым потомком JTextField, поэтому для него справедливо все сказанное выше.
Область для ввода текста JTextArea
JTextArea также является потомком JTextField и наследует все его методы.
Панель прокрутки JScrollPane
JScrollPane — панель прокрутки. Чаще всего она просто «надевается» на требуемый объект посредством собственного конструктора, принимающего этот объект в качестве параметра. Например, чтобы текстовая область textArea из предыдущего примера обрела полосы прокрутки, необходимо заменить команду
Инструментальная панель JToolBar
В Swing для инструментальных панелей разработан визуальный компонент JToolBar, в котором заложена просто потрясающая функциональность.
Выпадающий список JComboBox
Выпадающий список — весьма распространенный элемент управления. Он содержит множество вариантов, из которых пользователь может выбрать один и только один, либо (если выпадающий список это позволяет) ввести свой собственный.
Ползунок JSlider
Ползунок позволяет пользователю выбрать некоторое число из диапазона доступных значений, наглядно представив этот диапазон.
Панель со вкладками JTabbedPane
Многим программам бывает необходимо разместить в одном окне большое количество элементов управления, некоторые из которых (такие как списки, деревья, текстовые области и т.д.) могут к тому же занимать приличное пространство.
Список JList
Список содержит группу элементов, аналогично выпадающему списку JComboBox, но обладает двумя отличительными особенностями. Во-первых, на экране видны одновременно несколько элементов списка. Во-вторых, пользователь может выбрать в списке не один элемент, а несколько (если установлен соответствующий режим выделения).
Создать список можно с помощью конструктора, работающего на основе массива Object[] или вектора Vector (аналогично JComboBox).
JTable Таблицы
Для отображения табличных данных используется комопнент JTable. JTable внутри себя не содержит данные, а служит только для их отображения.
JFileChooser для выбора файла
При работе с файлами из приложения возникает необходимость рано или поздно использовать диалог для выбора файлов.
JProgressBar полоса загрузки
JMenuBar
Стандартные диалоговые окна
Менеджер размещения
Менеджер последовательного размещения FlowLayout
Менеджер граничного размещения BorderLayout
Менеджер размещения BorderLayout разделяет панель на пять областей: центральную, верхнюю, нижнюю, правую и левую. В каждую из этих областей можно добавить ровно по одному компоненту, причем компонент будет занимать всю отведенную для него область. Компоненты, добавленные в верхнюю и нижнюю области, будут растянуты по ширине. обавленные в правую и левую — по высоте, а компонент, добавленный в центр, будет растянут так, чтобы полностью заполнить оставшееся пространство панели.
При добавлении элемента на панель с менеджером размещения BorderLayout, необходимо дополнительно указывать в методе add(), какая из областей имеется в виду. Для этого служат строки с названиями сторон света: «North», «South», «East», «West» и «Center». Но вместо них рекомендуется использовать константы, определенные в классе BorderLayout: NORTH, SOUTH, EAST, WEST и CENTER (поскольку в строке можно допустить ошибку и не заметить этого, а при попытке написать неправильно имя константы компилятор выдаст предупреждение).
Менеджер табличного размещения GridLayout
GridLayout разбивает панель на ячейки одинаковой ширины и высоты (таким образом окно становится похожим на таблицу). Каждый элемент, добавляемый на панель с таким расположением, целиком занимает одну ячейку. Ячейки заполняются элементами по очереди, начиная с левой верхней.
Этот менеджер, в отличие от рассмотренных ранее, создается конструктором с параметрами (четыре целых числа). Необходимо указать количество столбцов, строк и расстояние между ячейками по горизонтали и по вертикали.
Менеджер блочного размещения BoxLayout и класс Box
Менеджер BoxLayout размещает элементы на панели в строку или в столбец. Обычно для работы с этим менеджером используют вспомогательный класс Box, представляющий собой панель, для которой уже настроено блочное размещение. Создается такая панель не конструктором, а одним из двух статических методов, определенных в классе Box: createHorizontalBox() и createVerticalBox().
Элементы, добавленные на панель с блочным размещением, выстраиваются один за другим. Расстояние между элементами по умолчанию нулевое. Однако вместо компонента можно добавить невидимую «распорку», единственная задача которой — раздвигать соседние элементы, обеспечивая между ними заданное расстояние.
Горизонтальная распорка создается статическим методом createHorizontalStrut(int width), а вертикальная — методом createVerticalStrut(int height). Оба метода определены в классе Box, а целочисленный параметр в каждом из них определяет размер распорки.
Ручное размещение элементов
Если в качестве менеджера размещения панели установить null, элементы не будут расставляться автоматически. Координаты каждого элемента необходимо в этом случае указать явно, при этом они никак не зависят от размеров панели и от координат других элементов. По умолчанию координаты равны нулю (т.е. элемент расположен в левом верхнем углу панели). Размер элемента также необходимо задавать явно (в противном случае его ширина и высота будут равны нулю и элемент отображаться не будет). Координаты элемента можно задать одним из следующих методов:
Java setResizable (false) изменяет размер окна (swing)
У меня странная проблема. Я использую нулевой макет для окна (= JFrame и для окон), и если я использую setResizable (false), размер окна становится больше (справа и внизу, около 10 пикселей, я бы сказал). Я не знаю, почему.
Два println возвращают одинаковые размеры, что странно, также…
Есть ли у кого-то идея? Почему окно изменяется?
UPDATE:
То же самое здесь (скомпилируйте его с помощью setResizable и без него, и вы можете увидеть его, если вы перекрываете окна):
В моем примере это не меняется, поэтому у вас должно быть что-то еще, что вызывает вашу проблему:
В некоторых случаях вставки неверны, если вы устанавливаете изменяемый размер в false (по крайней мере, в Windows 7 и JDK 6). Так или иначе они меняются от 30,8,8,8 до 25,3,3,3, хотя граница (которая окрашена ОС) остается на самом деле одинаковой. Поскольку вставки являются частью границ кадра, кадр на самом деле слишком большой (визуально), когда он не изменяется. Для меня это похоже на ошибку в вычисленных вставках, когда кадр не изменяется.
Если вы установите setResizable false перед установкой границ, у вас не будет проблемы. как ранее заявлял Гергили Ссилаги, вы избавляетесь от полос прокрутки, но размер окна заблокирован, и поэтому вы получаете 9 или 10 пикселей дополнительного пространства в кадре. У меня была такая же проблема. спасибо за помощь.
В зависимости от настройки L & F изменяемый размер (false/true) может изменить декорации границ окна. Без увеличения, без изменения размера стрелки. Это само по себе может изменить размер.
У меня есть 2 подкласса JFrame. Если я запускаю проблему в автономном приложении, размер кадра правильный. Если я запускаю оба фрейма в автономном приложении, проблема будет еще больше. Я сделал setResizable (false) перед пакетом, и у меня все еще проблема. Мое обходное решение состояло в том, чтобы изменить макет на BorderLayout и перевернуть панель (изображение) в центре, а затем сделать setResizable.
Ну, я встретил эту проблему, и это проблема Look and Feel…
Почему у изменяемого размера рамки есть вставки (5, 5, 5, 5)? Это заставляет меня думать, что делает его изменчивым добавляет дополнительный компонент вокруг фрейма, например… какой-то “обработчик” для перетаскивания для изменения размера?
Мой собственный вопрос и мой ответ с GIF здесь:
Если кто-то отметит его как дубликат, я сделаю это сам: у нас есть очень относительный вопрос задолго до этого:
И ни одно решение не работает для меня. Вот мой SSCCE:
Я замечаю, что не только окна меняют размер, но и заголовок также меняет высоту. Это лучше иллюстрируется этим GIF:
Мы можем видеть все данные, которые нам нужны в этом примере. Когда кадр не изменяется:
Когда размер кадра изменяется:
Итак, когда кадр не будет изменяться, его панель содержимого добавит вставки (5, 5, 5, 5) и для поддержания общего размера JFrame, строка заголовка будет сжата на 10 пикселей. Это абсурдно.
Я тестировал с и без Nimbus L & F, это не имеет значения.
Как это можно и допускать?
Как мы можем это решить?
В конце концов, это проблема Look and Feel.
Если мы используем стиль Java по умолчанию Metal и устанавливаем setDefaultLookAndFeelDecorated(true) перед созданием обоих фреймов, границы/вставки стиля отображения по умолчанию Java по умолчанию будут нарисованы и видны, поэтому два JFrames имеют одинаковую ширину и высоту.
Этот GIF показывает вам, как по умолчанию Metal L & F рисует «дескриптор» изменения размера в обоих кадрах:
Java setResizable(false) changes the window size (swing)
I have a strange problem. I am using the null layout for a window (= JFrame and on windows) and if I use setResizable (false) the window size gets bigger (to right and bottom, around 10 pixels I would say). I do not know why.
The two println’s return the same sizes, what is strange, also.
Does somebody has an idea? Why does the window gets resized?
UPDATE: Same thing here (compile it with and without the setResizable and than you can see it, if you overlap the windows):
7 Answers 7
It does not change on my example, so you must have something else that causes your issue:
Somehow insets are incorrect when you set the resizable to false (at least on Windows 7 and JDK 6). Somehow they change from 30,8,8,8 to 25,3,3,3 although the border (which is painted by the OS) stays actually the same. Since insets are part of the bounds of the Frame, the frame is actually too big (visually) when it is not resizable. For me it looks like there is a bug in the computed insets when the frame is not resizable.
If you set setResizable false before setting the bounds, you will not have the problem. as Gergely Szilagyi stated before, you are getting rid of the scrollbars, but the size of the window is locked and therefore you end up with 9 or 10 pixels of extra space in the frame. I just had the same problem. thanks for the help.
Depending on the L&F setting the resizable(false/true) might change the window border decorations. No maximize, no resize arrow. That itself can change the size.
Well I have met this problem and it is a Look & Feel problem.
Why the resizable frame has an insets of (5, 5, 5, 5)? It leads me to think that make it resizable adds some extra component around the frame, like. some kind of «handler» to drag to resize?
My own question and my answer with GIF is here:
I have a 2 JFrame subclasses defined. If I run the problem frame in a standalone app, the frame size is correct. If I run both frames in a standalone app, the problem frame is still larger. I did setResizable(false) before pack, and I still get the problem. My workaround was to change the layout to BorderLayout and plop the (image) panel in the center, then did the setResizable.
Not the answer you’re looking for? Browse other questions tagged java swing window or ask your own question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
site design / logo © 2021 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2021.11.12.40742
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Java собеседование. Коллекции
С недавнего времени у меня появилась настойчивая мысль, что профессиональное развитие сильно замедлилось и это хочется как-то исправить. Да, читаю книги, слушаю курсы, но в то же время приходит и понимание того, что возможно пришло время сменить работу, здесь вроде как все изучено, плавно уходим в рутину. Данная мысль сподвигла меня на рассылку своего резюме в несколько компаний — лидеров рынка. После прохождения собеседования в 3 из них, я решил, как водится внести свои 5 копеек в освещение обширной темы собеседования, а именно технических вопросов по Java коллекциям, с которыми приходится сталкиваться. Да, знаю, читатель скажет: «коллекции — избитая тема, сколько можно», но часть из приведенных ниже вопросов, я задавал своим знакомым разработчикам, которые занимают именно позиции разработчиков («крепких середнячков», по меркам недалекой от Москвы глубинки, которые уверенно справляются со своей работой на практике, а вот в теории скажем так есть пробелы, потому, что работа не требует решения каких-то нетривиальных задач, да и потому что не всем это интересно — изучать как внутри работает структура данных), вызывало растерянность. Думаю, что рассмотренный материал будет не очень интересен разработчикам выше уровня Junior (я попрошу их комментировать, дополнять и критиковать изложенный здесь материал), а вот Junior`ы уверен, найдут в этой статье интересное для себя.
Признаюсь честно, сам при прохождении интервью не знал ответы на некоторые из изложенных ниже вопросов, хотя вроде как уже прошел этап джуниорства. Это вдвойне обидно, с учетом того, что позиции в те компании, где симпатию вызывало все, начиная от общения с HR и заканчивая возможной будущей сферой деятельности не удалось получить оффер и как раз там были вопросы по коллекциям, с которыми я не справился (уверен они внесли свою негативную лепту). А вот там, где все прошло вполне неплохо с точки зрения собеседования, предложенная сфера деятельности и общение в целом с будущими коллегами оставили негатив, так что закон «подлости» во всей красе. В итоге, данным топиком я хочу и в своей голове заполнить обнаруженные пробелы+систематизировать на «бумаге» эти знания.
В статье я рассмотрю не только вопросы, вызвавшие у меня сложности на последних собеседованиях, но и вопросы, которые мне задавали за всю мою практику прохождения собеседований. Ну что ж, думаю пора переходить к вопросам:
1. Чем отличается ArrayList от LinkedList?
В моем рейтинге это один из двух самых популярных вопросов о коллекции, задают в 90% случаев. Вызвал у меня проблему на моем первом собеседовании на Junior Developer`а. Вкратце ответ на этот вопрос сводится к следующему: ArrayList это список, реализованный на основе массива, а LinkedList — это классический связный список, основанный на объектах с ссылками между ними.
Преимущества ArrayList: в возможности доступа к произвольному элементу по индексу за постоянное время (так как это массив), минимум накладных расходов при хранении такого списка, вставка в конец списка в среднем производится так же за постоянное время. В среднем потому, что массив имеет определенный начальный размер n (в коде это параметр capacity), по умолчанию n = 10, при записи n+1 элемента, будет создан новый массив размером (n * 3) / 2 + 1, в него будут помещены все элементы из старого массива + новый, добавляемый элемент. В итоге получаем, что при добавлении элемента при необходимости расширения массива, время добавления будет значительно больше, нежели при записи элемента в готовую пустую ячейку. Тем не менее, в среднем время вставки элемента в конец списка является постоянным. Удаление последнего элемента происходит за константное время. Недостатки ArrayList проявляются при вставке/удалении элемента в середине списка — это взывает перезапись всех элементов размещенных «правее» в списке на одну позицию влево, кроме того, при удалении элементов размер массива не уменьшается, до явного вызова метода trimToSize().
LinkedList наоборот, за постоянное время может выполнять вставку/удаление элементов в списке (именно вставку и удаление, поиск позиции вставки и удаления сюда не входит). Доступ к произвольному элементу осуществляется за линейное время (но доступ к первому и последнему элементу списка всегда осуществляется за константное время — ссылки постоянно хранятся на первый и последний, так что добавление элемента в конец списка вовсе не значит, что придется перебирать весь список в поисках последнего элемента). В целом же, LinkedList в абсолютных величинах проигрывает ArrayList и по потребляемой памяти и по скорости выполнения операций. LinkedList предпочтительно применять, когда происходит активная работа (вставка/удаление) с серединой списка или в случаях, когда необходимо гарантированное время добавления элемента в список.
Для углубленного и в то же время экспресс обучения очень рекомендую к прочтению замечательные статьи tarzan82 о ArrayList и LinkedList. Так же порекомендую статью от lany о потреблении памяти коллекциями — очень познавательно.
2. Что вы обычно используете (ArrayList или LinkedList)? Почему?
Это вопрос является слегка замаскированной версией предыдущего, так как ответ на этот вопрос приведет к постепенному изложению ответа на предыдущей вопрос. В 90% случае ArrayList будет быстрее и экономичнее LinkedList, так что обычно используют ArrayList, но тем не менее всегда есть 10% случаев для LinkedList. Я говорю, что обычно ArrayList использую, ссылаясь на тесты и последний абзац из предыдущего вопроса, но не забываю и про LinkedList (в каких случаях? так же последний абзац предыдущего вопроса помогает).
3. Что быстрее работает ArrayList или LinkedList?
Еще одна замаскированная версия первого вопроса. Хитрее приведенных выше вариантов, что постановка вопроса подразумевает односложный ответ с выбором одного из предложенных вариантов, что, по задумке автора вопроса, как я понимаю, должно сразу выявить человека с неглубокими познаниями в collections. Правильным же действием будет встречный вопрос о том, какие действия будут выполняться над структурой. В итоге, диалог плавно переходит к ответу на первый вопрос.
4. Необходимо добавить 1млн. элемент, какую структуру вы используете?
Тоже довольно популярная скрытая версия первого вопроса. Так же постановка предполагает выбор одного из предложенных вариантов, хотя на самом деле информации для однозначного выбора нет. Нужно задавать дополнительные вопросы: в какую часть списка происходит добавление элементов? есть ли информация о том, что потом будет происходить с элементами списка? какие то ограничения по памяти или скорости выполнения? В целом, все тот же первый вопрос, но немного с другой стороны: вы через дополнительные вопросы, показываете глубину понимания работы Array и Linked List.
Однажды я сам «клюнул» на этот крючок, домыслив про себя, что добавить — это «вставить» в конец списка и усиленно продвигал ArrayList, хотя ничего не знал (и не пытался узнать) про дальнейшие действие с этим списком и возможные ограничения.
5. Как происходит удаление элементов из ArrayList? Как меняется в этом случае размер ArrayList?
Опять же, ответ на вопрос 1 содержит ответ и на этот вопрос. При удалении произвольного элемента из списка, все элементы находящиеся «правее» смещаются на одну ячейку влево и реальный размер массива (его емкость, capacity) не изменяется никак. Механизм автоматического «расширения» массива существует, а вот автоматического «сжатия» нет, можно только явно выполнить «сжатие» командой trimToSize().
6. Предложите эффективный алгоритм удаления нескольких рядом стоящих элементов из середины списка, реализуемого ArrayList.
Неизбитый, по моим меркам вопрос, встречался мне всего однажды, когда я не знал механизма удаления элементов из ArrayList. В итоге вызвал у меня серьезные затруднения. На самом деле все довольно просто и очевидно, когда знаешь как происходит удаление одного элемента. Допустим нужно удалить n элементов с позиции m в списке. Вместо выполнения удаления одного элемента n раз (каждый раз смещая на 1 позицию элементы, стоящие «правее» в списке), нужно выполнить смещение всех элементов, стоящих «правее» n+m позиции на n элементов левее к началу списка. Таким образом, вместо выполнения n итераций перемещения элементов списка, все выполняется за 1 проход.
7. Как устроена HashMap?
Это второй из списка самых популярных вопросов по коллекциям. Уж даже не помню был ли случай, когда этот вопрос мне не задавали.
Вкратце, HashMap состоит из «корзин» (bucket`ов). С технической точки зрения «корзины» — это элементы массива, которые хранят ссылки на списки элементов. При добавлении новой пары ключ-значение, вычисляет хеш-код ключа, на основании которого вычисляется номер корзины (номер ячейки массива), в которую попадет новый элемент. Если корзина пустая, то в нее сохраняется ссылка на вновь добавляемый элемент, если же там уже есть элемент, то происходит последовательный переход по ссылкам между элементами в цепочке, в поисках последнего элемента, от которого и ставится ссылка на вновь добавленный элемент. Если в списке был найден элемент с таким же ключом, то он заменяется. Добавление, поиск и удаление элементов выполняется за константное время. Вроде все здорово, с одной оговоркой, хеш-функций должна равномерно распределять элементы по корзинам, в этом случае временная сложность для этих 3 операций будет не ниже lg N, а в среднем случае как раз константное время.
В целом, этого ответа вполне хватит на поставленный вопрос, дальше скорее всего завяжется диалог по HashMap, с углубленным пониманием процессов и тонкостей.
Опять же, рекомендую к прочтению статью tarzan82 по HashMap.
8. Какое начальное количество корзин в HashMap?
Довольно неожиданный вопрос, опять же меня он когда-то заставил угадывать число корзин при использовании конструктора по умолчанию.
Ответ здесь — 16. Отвечая, стоит заметить, что можно используя конструкторы с параметрами: через параметр capacity задавать свое начальное количество корзин.
9. Какая оценка временной сложности выборки элемента из HashMap? Гарантирует ли HashMap указанную сложность выборки элемента?
Ответ на первую часть вопроса, можно найти в ответе на вопрос 7 — константное время необходимо для выборки элемента. Вот на второй части вопроса, я недавно растерялся. И устройство HashMap знал и про хеш-функцию тоже знал, а вот к такому вопросу не был готов, в уме кинулся вообще в другом направлении и сосредоточился на строении HashMap откинув проблему хеш-кода, который в голове всегда привык считать хеш-кодом с равномерным распределением. На самом деле ответ довольно простой и следует из ответа вопроса 7.
Если вы возьмете хеш-функцию, которая постоянно будет возвращать одно и то же значение, то HashMap превратится в связный список, с отвратной производительностью. Затем даже, если вы будете использовать хеш-функцию с равномерным распределением, в предельном случае гарантироваться будет только временная сложность lg N. Так что, ответ на вторую часть вопроса — нет, не гарантируется.
10. Роль equals и hashCode в HashMap?
Ответ на этот вопрос следует из ответа на вопрос 7, хотя явно там и не прописан. hashCode позволяет определить корзину для поиска элемента, а equals используется для сравнения ключей элементов в списке внутри корзины и искомого ключа.
11. Максимальное число значений hashCode()?
Здесь все довольно просто, достаточно вспомнить сигнатуру метода: int hashCode(). То есть число значений равно диапазону типа int — 2^32 (точного диапазона никогда не спрашивали, хватало такого ответа).
12. Как и когда происходит увеличение количества корзин в HashMap?
Вот это довольно тонкий вопрос. Как показал мой мини-опрос, если суть устройства HashMap себе представляют многие более-менее ясно, то этот вопрос часто ставил собеседника в тупик.
Помимо capacity в HashMap есть еще параметр loadFactor, на основании которого, вычисляется предельное количество занятых корзин (capacity*loadFactor). По умолчанию loadFactor = 0,75. По достижению предельного значения, число корзин увеличивается в 2 раза. Для всех хранимых элементов вычисляется новое «местоположение» с учетом нового числа корзин.
13. В каком случае может быть потерян элемент в HashMap?
Этот интересный вопрос мне прислал LeoCcoder, у меня подобного не спрашивали и честно признаюсь, после прочтения сходу не смог придумать сценарий для потери элемента. Все опять же оказалось довольно просто, хоть и не так явно: допустим в качестве ключа используется не примитив, а объект с несколькими полями. После добавления элемента в HashMap у объекта, который выступает в качестве ключа, изменяют одно поле, которое участвует в вычислении хеш-кода. В результате при попытке найти данный элемент по исходному ключу, будет происходить обращение к правильной корзине, а вот equals (ведь equals и hashCode должны работать с одним и тем же набором полей) уже не найдет указанный ключ в списке элементов. Тем не менее, даже если equals реализован таким образом, что изменение данного поля объекта не влияет на результат, то после увеличения размера корзин и пересчета хеш-кодов элементов, указанный элемент, с измененным значением поля, с большой долей вероятности попадет совсем в другую корзину и тогда он уже совсем потеряется.
14. Почему нельзя использовать byte[] в качестве ключа в HashMap?
Еще один вопрос от LeoCcoder. Как обычно, все оказалось довольно просто — хеш-код массива не зависит от хранимых в нем элементов, а присваивается при создании массива (метод вычисления хеш-кода массива не переопределен и вычисляется по стандартному Object.hashCode() на основании адреса массива). Так же у массивов не переопределен equals и выполняет сравнение указателей. Это приводит к тому, что обратиться к сохраненному с ключом-массивом элементу не получится при использовании другого массива такого же размера и с такими же элементами, доступ можно осуществить лишь в одном случае — при использовании той же самой ссылки на массив, что использовалась для сохранения элемента. За ответ на этот вопрос отдельная благодарность уходит пользователю @dark_dimius.
15. В чем отличия TreeSet и HashSet?
Начнем с того, что Set — это множество (так же называют «набором»). Set не допускает хранение двух одинаковых элементов. Формально говоря, термин «множество» и так обозначает совокупность различных элементов, очень важно, что именно различных элементов, так как это главное свойство Set. С учетом такого определения, пояснение про хранение одинаковых элементом не требуется, но в обиходе, понятие «множество» потеряло свой строгий смысл касательно уникальности элементов, входящих в него, поэтому все же уточняйте отдельно данное свойство множества.
TreeSet обеспечивает упорядоченно хранение элементов в виде красно-черного дерева. Сложность выполнения основных операций в TreeSet lg N. HashSet использует для хранения элементов такой же подход, что и HashMap, за тем отличием, что в HashSet в качестве ключа выступает сам элемент, кроме того HashSet (как и HashMap) не поддерживает упорядоченное хранение элементов и обеспечивает временную сложность выполнения операций аналогично HashMap.
16. Устройство TreeSet?
Этот вопрос задают вместо вопроса 14 и здесь достаточно краткого ответа, что TreeSet основан на красно-черном дереве. Как правило этого хватает и собеседник сразу переходит к следующему вопросу, у меня ни разу не спрашивали механизм балансировки дерева или другие подробности его реализации.
Для экспресс углубления знаний по красно-черному дереву рекомендую вот эту статью.
17. Что будет, если добавлять элементы в TreeSet по возрастанию?
Обычно данный вопрос собеседник предваряет фразой, что в основе TreeSet лежит бинарное дерево и если добавлять элементы по возрастанию, то как они будут распределены по дереву.
Если нет точного представления об устройстве TreeSet, а есть общее понимание о том, что это бинарное дерево (в чем нас дополнительно уверяет собеседник), то данный вопрос может привести к интересному результату: все элементы после доабвления в обычное бинарное дерево будут находится в одной ветви длиной N элементов, что сводит на нет, все преимущества такой структуры, как дерево (фактически получается список). На самом, деле, как выше упоминалось в основе TreeSet лежит красно-черное дерево, которое умеет само себя балансировать. В итоге, TreeSet все равно в каком порядке вы добавляете в него элементы, преимущества этой структуры данных будут сохраняться.
Надеюсь, рассмотренные вопросы будут полезны хабраюзерам. Прошу так же простить мне возможную некоторую наивность в том, что приведенные выше вопросы требуют такого детального рассмотрения, но в свое время подобная статья мне бы серьезно помогла. Уверен, что в статье присутствуют неточности — прошу в комментарии, кроме того, надеюсь, что более опытные товарищи в комментариях будут активно делится вопросами из своей практики и, если статья будет благосклонно принята хабрасообществом, то вполне возможно продолжение обзора технических вопросов для Java собеседований.