Немного необходимого в Java.
Решил написать несколько теоретический пост,про основные понятия в Java,которые нужно знать каждому(по моему мнению).
Есть много вроде простых вопросов,на которые очень мало кто может ответить, еще их достаточно часто могут спросить и на собеседованиях)
Есть много вроде простых вопросов,на которые очень мало кто может ответить, еще их достаточно часто могут спросить и на собеседованиях)
В общем не будет лишним заметка.
Поехали:
Самый популярный вопрос:
Что такое Hashmap и как он работает?
Да все просто на самом деле.
Map - интерфейс, описывающий классы, предназначенные для хранения пар объектов. Один из объектов пары должен быть уникальным - называется "ключом" (key), второй объект, необязательно уникальный, называется "значением" (value). Всю пару называют "записью" (entry).
Уникальный - значит не равный другим ключам. Как определить "равность"? Достаточно знать, что ключи в Map сравниваются по методу equals(), и при попытке добавить в Map запись с не уникальным ключом предыдущая запись будет затерта новой.
Как HashMap устроен внутри?
Внутри HashMap - это массив. Элементы массива в документации называются бакетами (buckets). В бакете хранится первый элемент связанного списка.Таким образом, HashMap внутри - массив связанных списков. Элемент связанного списка - объект класса Entry, содержит ключ, значение и ссылку на следующий Entry.
Внутри HashMap - это массив. Элементы массива в документации называются бакетами (buckets). В бакете хранится первый элемент связанного списка.Таким образом, HashMap внутри - массив связанных списков. Элемент связанного списка - объект класса Entry, содержит ключ, значение и ссылку на следующий Entry.
Что происходит при добавлении записи?
На следующем шаге, рассчитывается хеш-значение используя хеш-код ключа, получаемый вызовом метода hashCode(). Это хеш-значение используется для вычисления позиции в массиве, куда будет помещен объектEntry. Дизайнеры JDK предполагали, что плохо написанная функция hashCode() может вернуть слишком высокое или слишком низкое значение хеш-кода. Для решения этой проблемы, они ввели другую hash() функцию, и передали в нее значение хеш-кода объекта, чтобы привести хеш-значение в соответствие с размером массива.Теперь вызывается функция indexFor(hash, table.length), для вычисления точной позиции, куда будет помещен объект Entry
Далее, найдя нужный бакет, запись помещается в соответствующий связанный список.
А как искать элемент?
Поиск производится по ключу (ключ для поиска). Опять же по hashcode() ключа находим нужный бакет. Нашли бакет - значит нашли нужный нам связанный список. Далее проходим по списку и сравниваем ключи элементов списка с нашим ключом для поиска. Сравнение производим по функции equals(). Вернула функция true - значит нашли.
И для чего все это нужно?
Для ускорения работы. В первую очередь ускорение поиска. Напомню, соответствие между hashcode ключа и бакетом не хранится, а вычисляется. Математические вычисления - это быстро. Далее, сравнивать объекты по equals() все же придется, но количество этих объектов ограничено.
На следующем шаге, рассчитывается хеш-значение используя хеш-код ключа, получаемый вызовом метода hashCode(). Это хеш-значение используется для вычисления позиции в массиве, куда будет помещен объектEntry. Дизайнеры JDK предполагали, что плохо написанная функция hashCode() может вернуть слишком высокое или слишком низкое значение хеш-кода. Для решения этой проблемы, они ввели другую hash() функцию, и передали в нее значение хеш-кода объекта, чтобы привести хеш-значение в соответствие с размером массива.Теперь вызывается функция indexFor(hash, table.length), для вычисления точной позиции, куда будет помещен объект Entry
Далее, найдя нужный бакет, запись помещается в соответствующий связанный список.
А как искать элемент?
Поиск производится по ключу (ключ для поиска). Опять же по hashcode() ключа находим нужный бакет. Нашли бакет - значит нашли нужный нам связанный список. Далее проходим по списку и сравниваем ключи элементов списка с нашим ключом для поиска. Сравнение производим по функции equals(). Вернула функция true - значит нашли.
И для чего все это нужно?
Для ускорения работы. В первую очередь ускорение поиска. Напомню, соответствие между hashcode ключа и бакетом не хранится, а вычисляется. Математические вычисления - это быстро. Далее, сравнивать объекты по equals() все же придется, но количество этих объектов ограничено.
Есть такие понятия как loadfactor и capacity-но они простые,даже писать не буду)
Как то много получилось про HashMap сейчас попробую короче укладываться.
В чем отличие между static synchronized и просто synchronized?
Использование слова synchronize на static-методе помечает весь класс как synchronize, т.е. такая запись:
равнозначна такой:
А такая:
такой:
Что значит synchronized(this)?
Семантически этот код:
эквивалентен этому:
Однако synchronized(this) использовать не рекомендуется. Почему? Об этом можно почитать тут .
Использование слова synchronize на static-методе помечает весь класс как synchronize, т.е. такая запись:
1
2
3
| synchronized static void foo() { ... } |
1
2
3
4
5
| static void foo() { synchronized (SomeClass. class ) { ... } } |
1
2
3
| synchronized void foo() { ... } |
1
2
3
4
5
| void foo() { synchronized ( this ) { ... } } |
Семантически этот код:
1
2
3
4
5
| public void blah() { synchronized ( this ) { // do stuff } } |
1
2
3
| public synchronized void blah() { // do stuff } |
Что означают ключевые слова volatile и transient.
Определение переменной с ключевым словом volatile(«изменчивый») означает, что значение переменной будет изменяться несколькими потоками.
Переменная помеченая словом transient не будет сериализоваться и соответственно при десериализации её значение будет установлено значением по умолчанию.
Условия сериализации объектов?
Свойства класса должны быть сериализуемы и класс должен реализовывать маркирующий интерфейс Serializable. Не лишним будет вспомнить про serialVersionUID и его значение по умолчанию.
Можно ли передать объект в synchronized?
Да. Например очень популярна вот такая несложная конструкция:
1
2
3
4
5
6
7
8
9
| private final Object _SyncObject = new Object(); ... public void run() { ... synchronized (_SyncLock) { ... } ... } |
Об этом можно почитать тут.
Как сделать ArrayList синхронизированым в одну строку?
1
| List<Record> s_list = Collections.synchronizedList(list); |
Если equals возвращает true, то hashCode должен вернуть одно и то же значение. Обратное не верно.
Collections
Контейнеры бывают двух видов:
В ArrayList и LinkedList элементы хранятся в порядке вставки. Различаются скоростью выполнения и количеством тех или иных операций: ArrayList имеет оптимизированый доступ к элементам списка, но обладает низкой производительностью при добавлении/удалении элементов в середину списка. LinkedList - наоборот.
HashSet обеспечивает наибольшую производительность при выборке элементов. TreeSet хранит элементы отсортированными по возрастанию в порядке сравнения. LinkedHashSet хранит элменты в порядке добавления.
HashMap обеспечивает наибольшую производительность. TreeMap хранит ключи отсортированными. LinkedHashMap хранит ключи в порядке вставки, но обеспечивает скорость HashMap.
Контейнеры бывают двух видов:
- Коллекции (List, Set, Queue)
- Ассоциативный массив (Map)
В ArrayList и LinkedList элементы хранятся в порядке вставки. Различаются скоростью выполнения и количеством тех или иных операций: ArrayList имеет оптимизированый доступ к элементам списка, но обладает низкой производительностью при добавлении/удалении элементов в середину списка. LinkedList - наоборот.
HashSet обеспечивает наибольшую производительность при выборке элементов. TreeSet хранит элементы отсортированными по возрастанию в порядке сравнения. LinkedHashSet хранит элменты в порядке добавления.
HashMap обеспечивает наибольшую производительность. TreeMap хранит ключи отсортированными. LinkedHashMap хранит ключи в порядке вставки, но обеспечивает скорость HashMap.
Inner classes
Внутренний класс - класс, который объявлен внутри другого класса, например:
Анонимный внутренний класс - это класс, который определен в методе другого класса и может быть использован только один раз - там, где он определен. Примером анонимного внутреннего класса часто является реализация обработчика какого-либо события.
Внутренний класс - класс, который объявлен внутри другого класса, например:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // Outer.java public class Outer { Outer() { Inner i = new Inner(); i.innerMethod(); } // Inner class private class Inner { Inner() {} public void innerMethod() { // Do something. } } } |
Serialization
Сериализация это процесс сохранения состояния объекта в последовательность байт;десериализация это процесс восстановления объекта, из этих байт. Java Serialization API предоставляет стандартный механизм для создания сериализуемых объектов.
Сохранение объекта:
Восстановление объекта:
Сериализация это процесс сохранения состояния объекта в последовательность байт;десериализация это процесс восстановления объекта, из этих байт. Java Serialization API предоставляет стандартный механизм для создания сериализуемых объектов.
Сохранение объекта:
1
2
3
4
5
6
7
8
9
| FileOutputStream fos = new FileOutputStream( "temp.out" ); ObjectOutputStream oos = new ObjectOutputStream(fos); TestSerial ts = new TestSerial(); oos.writeObject(ts); oos.flush(); oos.close(); |
1
2
3
| FileInputStream fis = new FileInputStream( "temp.out" ); ObjectInputStream oin = new ObjectInputStream(fis); TestSerial ts = (TestSerial) oin.readObject();
|
В общем как то так,что то писал сам,что то дергал с других ресурсов.
Получилась не слишком длинная,но вполне возможно, что полезная шпаргалка.