1. Общ преглед
В този урок ще научим за различни начини за инициализиране на HashMap в Java.
Ще използваме Java 8, както и Java 9.
2. Статичният инициализатор за статична HashMap
Можем да инициализираме HashMap, използвайки статичен блок код:
public static Map articleMapOne; static { articleMapOne = new HashMap(); articleMapOne.put("ar01", "Intro to Map"); articleMapOne.put("ar02", "Some article"); }
Предимството на този вид инициализация е, че картата е променлива, но тя ще работи само за статични. Следователно записите могат да се добавят и премахват, когато и когато е необходимо.
Да продължим и да го тестваме:
@Test public void givenStaticMap_whenUpdated_thenCorrect() { MapInitializer.articleMapOne.put( "NewArticle1", "Convert array to List"); assertEquals( MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List"); }
Също така можем да инициализираме картата, като използваме синтаксиса на двойните скоби:
Map doubleBraceMap = new HashMap() {{ put("key1", "value1"); put("key2", "value2"); }};
Имайте предвид, че трябва да се опитаме да избегнем тази техника на инициализация, защото тя създава анонимен допълнителен клас при всяко използване, съдържа скрити препратки към заграждащия обект и може да причини проблеми с изтичане на памет.
3. Използване на Java Collections
Ако трябва да създадем еднократна неизменяема карта с един запис, Collections.singletonMap () става много полезен:
public static Map createSingletonMap() { return Collections.singletonMap("username1", "password1"); }
Имайте предвид, че картата тук е неизменна и ако се опитаме да добавим още записи, тя ще хвърли java.lang.UnsupportedOperationException.
Също така можем да създадем неизменяема празна карта, като използваме Collections.emptyMap ():
Map emptyMap = Collections.emptyMap();
4. Java 8 Way
В този раздел нека разгледаме начините за инициализиране на карта с помощта на Java 8 Stream API.
4.1. Използване на Collectors.toMap ()
Нека използваме поток от двуизмерен масив String и ги съберем в карта:
Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }).collect(Collectors.toMap(data -> data[0], data -> data[1]));
Забележете тук, че типът данни и ключът на картата са еднакви.
За да го направим по-общ, нека вземем масива от обекти и изпълним същата операция:
Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, }).collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1]));
В резултат на това създаваме карта на ключа като String и стойност като Integer .
4.2. Използване на поток от Map.Entry
Тук ще използваме екземплярите на Map.Entry. Това е друг подход, при който имаме различни типове ключ и стойност.
Първо, нека използваме реализацията на SimpleEntry на интерфейса Entry :
Map map = Stream.of( new AbstractMap.SimpleEntry("idea", 1), new AbstractMap.SimpleEntry("mobile", 2)) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Сега нека създадем картата, използвайки реализацията SimpleImmutableEntry :
Map map = Stream.of( new AbstractMap.SimpleImmutableEntry("idea", 1), new AbstractMap.SimpleImmutableEntry("mobile", 2)) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
4.3. Инициализиране на неизменяема карта
В определени случаи на употреба трябва да инициализираме неизменяема карта. Това може да се направи чрез обвиване на Collectors.toMap () в Collectors.collectingAndThen () :
Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }).collect(Collectors.collectingAndThen( Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap));
Имайте предвид, че трябва да избягваме да използваме такава инициализация, като използваме потоци, тъй като това може да доведе до огромни режийни разходи и много обекти за боклук се създават само за инициализиране на картата.
5. Java 9 Way
Java 9 се предлага с различни фабрични методи в интерфейса Map, които опростяват създаването и инициализирането на неизменяеми карти.
Нека да продължим и да разгледаме тези фабрични методи.
5.1. Map.of ()
Този фабричен метод не взема аргумент, единичен аргумент и аргументи с променлива:
Map emptyMap = Map.of(); Map singletonMap = Map.of("key1", "value"); Map map = Map.of("key1","value1", "key2", "value2");
Имайте предвид, че този метод поддържа само максимум 10 двойки ключ-стойност.
5.2. Map.ofEntries ()
Подобно е на Map.of (), но няма ограничения за броя двойки ключ-стойност:
Map map = Map.ofEntries( new AbstractMap.SimpleEntry("name", "John"), new AbstractMap.SimpleEntry("city", "budapest"), new AbstractMap.SimpleEntry("zip", "000000"), new AbstractMap.SimpleEntry("home", "1231231231") );
Имайте предвид, че фабричните методи създават неизменяеми карти, поради което всяка мутация ще доведе до UnsupportedOperationException.
Освен това те не позволяват нулеви ключове или дублирани ключове.
Сега, ако се нуждаем от променяща се или нарастваща карта след инициализация, можем да създадем някоя от реализациите на интерфейса Map и да предадем тези неизменяеми карти в конструктора:
Map map = new HashMap ( Map.of("key1","value1", "key2", "value2")); Map map2 = new HashMap ( Map.ofEntries( new AbstractMap.SimpleEntry("name", "John"), new AbstractMap.SimpleEntry("city", "budapest")));
6. Използване на Гуава
Тъй като разгледахме начините за използване на основната Java, нека продължим напред и да инициализираме карта с помощта на библиотеката Guava:
Map articles = ImmutableMap.of("Title", "My New Article", "Title2", "Second Article");
Това би създало неизменяема карта и да създаде изменяема:
Map articles = Maps.newHashMap(ImmutableMap.of("Title", "My New Article", "Title2", "Second Article"));
Методът ImmutableMap.of () също има претоварени версии, които могат да вземат до 5 двойки параметри ключ-стойност. Ето как би изглеждал пример с 2 двойки параметри:
ImmutableMap.of("key1", "value1", "key2", "value2");
7. Заключение
В тази статия разгледахме различните начини за инициализиране на карта , особено за създаване на празни, единични, неизменяеми и променливи карти. Както виждаме, има огромно подобрение в тази област след Java 9.
Както винаги, примерният изходен код се намира в проекта Github. Примерите за Java 9 се намират тук, а примерът от Гуава тук.