Java hashmap in static class

Class HashMap

Type Parameters: K — the type of keys maintained by this map V — the type of mapped values All Implemented Interfaces: Serializable , Cloneable , Map Direct Known Subclasses: LinkedHashMap , PrinterStateReasons

Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable , except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

This implementation provides constant-time performance for the basic operations ( get and put ), assuming the hash function disperses the elements properly among the buckets. Iteration over collection views requires time proportional to the «capacity» of the HashMap instance (the number of buckets) plus its size (the number of key-value mappings). Thus, it’s very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.

An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.

Читайте также:  Коды символов html перенос строки

As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put ). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.

If many mappings are to be stored in a HashMap instance, creating it with a sufficiently large capacity will allow the mappings to be stored more efficiently than letting it perform automatic rehashing as needed to grow the table. Note that using many keys with the same hashCode() is a sure way to slow down performance of any hash table. To ameliorate impact, when keys are Comparable , this class may use comparison order among keys to help break ties.

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be «wrapped» using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:

Map m = Collections.synchronizedMap(new HashMap(. ));

The iterators returned by all of this class’s «collection view methods» are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the iterator will throw a ConcurrentModificationException . Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

This class is a member of the Java Collections Framework.

Источник

10 заметок о модификаторе Static в Java

Java-университет

10 заметок о модификаторе Static в Java - 1

Модификатор static в Java напрямую связан с классом. Если поле статично, значит оно принадлежит классу, если метод статичный — аналогично: он принадлежит классу. Исходя из этого, можно обращаться к статическому методу или полю, используя имя класса. Например, если поле count статично в классе Counter, значит, вы можете обратиться к переменной запросом вида: Counter.count. Прежде чем приступить к заметкам, давайте вспомним (а может быть, узнаем), что такое static и что может быть статическим в Java. Static — модификатор, применяемый к полю, блоку, методу или внутреннему классу. Данный модификатор указывает на привязку субъекта к текущему классу.

Статические поля

10 заметок о модификаторе Static в Java - 2

При обозначении переменной уровня класса мы указываем на то, что это значение относится к классу. Если этого не делать, то значение переменной будет привязываться к объекту, созданному по этому классу. Что это значит? А то, что если переменная не статическая, то у каждого нового объекта данного класса будет своё значение этой переменной, меняя которое мы меняем его исключительно в одном объекте: Например, у нас есть класс Car с нестатической переменной:

 Car orangeCar = new Car(); orangeCar.km = 100; Car blueCar = new Car(); blueCar.km = 85; System.out.println("Orange car - " + orangeCar.km); System.out.println("Blue car - " + blueCar.km); 
 Orange car - 100 Blue car - 85 

Как видим, у каждого объекта своя переменная, изменение которой происходит только для этого объекта. Ну а если у нас переменная статическая, то это глобальное значение — одно для всех: Теперь мы имеем Car со статической переменной:

 Orange car - 85 Blue car - 85 

Ведь переменная у нас одна на всех, и каждый раз мы меняем именно ее. К статическим переменным, как правило обращаются не по ссылке на объект — orangeCar.km, а по имени класса — Car.km

Статический блок

Есть два блока инициализации — обычный и статический. Блок предназначен для инициализации внутренних переменных. Если блок обычный, то им инициализируют внутренние переменные объекта, если же статический, соответственно, им задают статические переменные (то есть переменные класса). Пример класса со статическим блоком инициализации:

Статический метод

Статические методы отличаются от обычных тем, что они также привязаны к классу, а не к объекту. Важным свойством статического метода является то, что он может обратиться только к статическим переменным/методам. В качестве примера давайте рассмотрим класс, который у нас будет неким счётчиком, ведущим учет вызовов метода:

 Counter.invokeCounter(); Counter.invokeCounter(); Counter.invokeCounter(); 
 Текущее значение счётчика - 1 Текущее значение счётчика - 2 Текущее значение счётчика - 3 

Статический класс в Java

Статическим классом может быть только внутренний класс. Опять же, этот класс привязан к внешнему классу, и если внешний наследуется другим классом, то этот не будет наследован. При этом данный класс можно наследовать, как и он может наследоваться от любого другого класса и имплементировать интерфейс. По сути статический вложенный класс ничем не отличается от любого другого внутреннего класса за исключением того, что его объект не содержит ссылку на создавший его объект внешнего класса. Тем не менее, благодаря этому статический класс наиболее похож на обычный не вложенный, ведь единственное различие состоит в том, что он упакован в другой класс. В некоторых случаях для нас это преимущество, так как с него у нас есть доступ к приватным статическим переменным внешнего класса. Пример вложенного статического класса:

 Vehicle.Car car = new Vehicle.Car(); car.km = 90; 

Для использования статических методов/переменных/класса нам не нужно создавать объект данного класса. Конечно, следует учитывать модификаторы доступа. Например, поля private доступны только внутри класса, в котором они объявлены. Поля protected доступны всем классам внутри пакета (package), а также всем классам-наследникам вне пакета. Для более подробной информации ознакомьтесь со статьей “private vs protected vs public”. Предположим, существует статический метод increment() в классе Counter , задачей которого является инкрементирование счётчика count . Для вызова данного метода можно использовать обращение вида Counter.increment() . Нет необходимости создавать экземпляр класса Counter для доступа к статическому полю или методу. Это фундаментальное отличие между статическими и НЕ статическими объектами (членами класса). Еще раз напомню, что статические члены класса напрямую принадлежат классу, а не его экземпляру. То есть, значение статической переменной count будет одинаковое для всех объектов типа Counter . Далее в этой статье мы рассмотрим основополагающие аспекты применения модификатора static в Java, а также некоторые особенности, которые помогут понять ключевые концепции программирования.

Что должен знать каждый программист о модификаторе Static в Java

  1. Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:
 class Vehicle < public static void kmToMiles(int km)< System.out.println("Внутри родительского класса/статического метода"); >> class Car extends Vehicle < public static void kmToMiles(int km)< System.out.println("Внутри дочернего класса/статического метода "); >> public class Demo< public static void main(String args[])< Vehicle v = new Car(); v.kmToMiles(10); >> 

Источник

Инициализировать статическую карту в Java

В этом посте будут обсуждаться различные методы инициализации статической карты в Java.

1. Использование статического блока инициализации

В Java мы можем использовать статический блок (или статический блок инициализации) для инициализации статических полей во время загрузки класса. Это будет работать, поскольку статический блок всегда выполняется после встроенных статических инициализаторов.

Хорошей практикой является обеспечение того, чтобы статическая карта не изменялась позже в любой момент. Мы можем сделать это, создав неизменяемая карта. Идея состоит в том, чтобы обернуть изменяемую карту с помощью Collections.unmodifiableMaput() и создание неизменяемый вид исходной карты только для чтения.

Для создания карты с несколькими записями лучше создать типобезопасную Builder класс, как показано ниже. Затем мы можем использовать Builder put() метод, который принимает пары ключ-значение вместо карты. put() связывает ключ со значением в построенной карте.

2. Использование статического метода

Мы можем сделать создание карты более явным, используя статический метод для ее инициализации, как показано ниже:

3. Использование Java 8

Мы можем использовать поток Java 8 для создания статических карт, получая поток из статических фабричных методов, таких как Stream.of() или же Arrays.stream() и накопление входных элементов в новую карту с использованием collectors.

Например, для инициализации карты с разными типами ключа и значения Map , мы можем сделать что-то вроде:

Другой подход, который позволяет легко использовать различные типы ключа и значения, заключается в создании потока записей карты. Есть две реализации Map.Entry интерфейс в java.util.AbstractMap : SimpleEntry а также SimpleImmutableEntry . Следующий пример демонстрирует использование AbstractMap.SimpleEntry :

4. Использование Java 9

В Java 9 очень удобно создавать экземпляры карты, предоставляя статический фабричный метод. of() на Map интерфейс, который может создать компактный немодифицируемый экземпляр Map. Например,

Обратите внимание, что Map.of() может поддерживать до 10 пар ключ-значение. Не существует перегрузки var-args Map.of() , который может обрабатывать любое количество отображений. Чтобы создать карту с произвольным количеством записей, мы можем использовать Map.ofEntries(Map.Entry…) .Он включает в себя перегрузку varargs, поэтому нет фиксированного ограничения на размер карты. Этот подход требует, чтобы каждая пара ключ-значение была упакована. Для упаковки ключей и значений мы можем использовать Map.Entry entry(K k, V v) .

Источник

Оцените статью