Map with one element java

Как создать HashMap сразу с элементами?

Проблема с созданием Map в том, что в отличие от других коллекций инициализация должна принять параметрами набор пар неопределенного размера. Поэтому varargs здесь не подходит.

Самый примитивный, многословный, но простой способ – добавить элементы сразу после создания. Для мапы-поля класса это можно сделать в конструкторе или блоке инициализации.


Map map = new HashMap<>();
map.put("one", "first");
map.put("two", "second");
>

Идиома double brace initialization. Компактная запись, которая расшифровывается компилятором как создание анонимного класса-наследника от HashMap , с добавлением элементов в блоке статической инициализации. Создание нового класса приводит к дополнительным накладным расходам, так делать не рекомендуется.


new HashMap() put("one", "first");
put("two", "second");
>>;

Для специальных случаев, пустой и одноэлементной неизменяемых мап, в классе Collections есть соответствующие фабричные методы emptyMap() и singletonMap(key, value) .

Удобно создавать HashMap из стрима. Коллектор Collectors.toMap(keyMapper, valueMapper) с помощью мапперов превратит объекты потока в ключи и значения.

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

До Java 9 подобное было реализовано во многих популярных библиотеках, например ImmutableMap.of в Guava и MapUtils.putAll() в Apache Commons.

Источник

Initialize Map with Values in Java

In this tutorial, we’ll learn different ways to initialize a Map with values in Java.

Using Map.of() and Map.ofEntries()

It is possible to initialize a Map with values in a single expression if you are using Java 9 or higher version using Map.of() and Map.ofEntries() method. This is shortest possible way so far.

Map.of()

Java 9 provides mutiple Map.of() overloaded methods to initialize a Map with upto 10 key-value pairs.

MapString, Integer> emptyMap = Map.of(); MapString, Integer> singletonMap = Map.of("A", 1); MapString, Integer> map = Map.of("A", 1, "B", 2, "C", 3); 
Map.ofEntries()

If you have more than 10 key-value pairs to initialize, then you should use Map.ofEntries() method. This method has no limit and you can define any number of key-value pairs.

MapString, Integer> map = Map.ofEntries(  Map.entry("A", 1),  Map.entry("B", 2),  Map.entry("C", 3),  Map.entry("D", 4),  Map.entry("E", 5),  Map.entry("F", 6),  Map.entry("G", 7),  Map.entry("H", 8),  Map.entry("I", 9),  Map.entry("J", 10),  Map.entry("K", 11),  Map.entry("L", 12) );  map.put("M", 13); // Throw UnsupportedOperationException  map.remove("A"); // Throw UnsupportedOperationException 
Mutable Map

Thing to note that both Map.of() and Map.ofEntries() return an immutable map which means that adding or removing an element in Map result into java.lang.UnsupportedOperationException exception.

You can avoid this by creating a mutable map (by copying the immutable map to new HashMap ) in this way:-

MapString, Integer> mutableEmptyMap = new HashMap<>(Map.of()); MapString, Integer> mutableSingletonMap = new HashMap<>(Map.of("A", 1)); MapString, Integer> mutableMap = new HashMap<>(Map.ofEntries(  Map.entry("A", 1),  Map.entry("B", 2),  Map.entry("C", 3),  Map.entry("D", 4),  Map.entry("E", 5),  Map.entry("F", 6),  Map.entry("G", 7),  Map.entry("H", 8),  Map.entry("I", 9),  Map.entry("J", 10),  Map.entry("K", 11),  Map.entry("L", 12) ));  mutableMap.put("M", 13); // It works!  mutableMap.remove("A"); // It works! 

Using Java Collections

Java Collections class provide methods to initialize emptyMap() , singletonMap() and unmodifiableMap() . Note that all these methods return immutable map

MapString, Integer> emptyMap = Collections.emptyMap(); MapString, Integer> singletonMap = Collections.singletonMap("A", 1);  singletonMap.put("B", 2); // Throw UnsupportedOperationException  singletonMap.remove("A"); // Throw UnsupportedOperationException  MapString, Integer> mutableMap = new HashMap<>(singletonMap); mutableMap.put("B", 2); // It works!  MapString, Integer> immutableMap = Collections.unmodifiableMap(mutableMap); immutableMap.put("B", 2); // Throw UnsupportedOperationException 

Initialize Map as an instance variable

If you initialize a Map as an instance variable, keep the initialization in a constructor or instance initializer:-

public class MyClass    MapString, Integer> instanceMap = new HashMap<>();    instanceMap.put("A", 1);  instanceMap.put("B", 2);  > > 

Initialize Map as a static variable

If you initialize a Map as a static class variable, keep the initialization in a static initializer:-

public class MyClass    static MapString, Integer> staticMap = new HashMap<>();  static  staticMap.put("A", 1);  staticMap.put("B", 2);  > > 

Using Double Brace Initialization

You can initialize map with values using Double Brace Initialization:-

MapString, Integer> map = new HashMap<>()  < put("A", 1);  put("B", 2); >>; 

In Double brace initialization > , first brace creates a new Anonymous Inner Class, the second brace declares an instance initializer block that is run when the anonymous inner class is instantiated.

This approach is not recommended as it creates an extra class at each usage. It also holds hidden references to the enclosing instance and any captured objects. This may cause memory leaks or problems with serialization.

The alternative approach for this is to create a function to initialize a map:-

// It works for all Java versions, mutable map.  MapString, Integer> map = createMap(); map.put("C", "3"); // It works!  private static MapString, String> createMap()   MapString, Integer> map = new HashMap<>();  map.put("A", 1);  map.put("B", 2);  return map; > 

Using Stream Collectors.toMap()

We can also use Java 8 Stream API to initialize a Map with values.

When both key and value are of same type (e.g. String):-

MapString, String> mutableMap1 = Stream.of(new String[][]  "A", "a">,  "B", "b">,  "C", "c"> >).collect(Collectors.toMap(p -> p[0], p -> p[1])); 

When both key and value are of different type (e.g. String and Integer):-

MapString, Integer> mutableMap2 = Stream.of(new Object[][]  "A", 1>,  "B", 2>,  "C", 3> >).collect(Collectors.toMap(p -> (String) p[0], p -> (Integer) p[1])); 

Another approach that can easily accommodate different types for key and value involves creating a stream of map entries.

MapString, Integer> mutableMap3 = Stream.of(  new AbstractMap.SimpleEntry<>("A", 1),  new AbstractMap.SimpleEntry<>("B", 2),  new AbstractMap.SimpleEntry<>("C", 3))  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));  MapString, Integer> mutableMap4 = Stream.of(  new AbstractMap.SimpleImmutableEntry<>("A", 1),  new AbstractMap.SimpleImmutableEntry<>("B", 2),  new AbstractMap.SimpleImmutableEntry<>("C", 3))  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 

The only difference between SimpleEntry and SimpleImmutableEntry is that you can set the value of SimpleEntry instance once initialized whereas set value of SimpleImmutableEntry after initialization throw UnsupportedOperationException .

Note that all the maps we have initialized using streams so far are mutable map means we can add or remove elements from them. You can initialize an immutable map using streams in this way:-

 MapString, Integer> map5 = Stream.of(  new AbstractMap.SimpleEntry<>("A", 1),  new AbstractMap.SimpleEntry<>("B", 2),  new AbstractMap.SimpleEntry<>("C", 3))  .collect(Collectors.collectingAndThen(  Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue),  Collections::unmodifiableMap  )); 

Conclusion

Let’s look at the summary of all the ways to initialize a Map with values:-

  1. Using Map.of() and Map.ofEntries() – Recommended this single line expression if you use Java 9 and above
  2. Using Java Collections – Works with all Java versions. Useful to define singleton map upto Java 8
  3. Using Double Brace Initialization — Avoid Double braces initialization. Create a method instead.
  4. Initialize Map as an instance variable — Recommended to initialize instance variable
  5. Initialize Map as a static variable — Recommended to initialize static variable
  6. Using Stream Collectors.toMap() – Too many lines of code. We can use other alternatives if possible to avoid boilerplate code.

See Also

Ashish Lahoti avatar

Ashish Lahoti is a Software Engineer with 12+ years of experience in designing and developing distributed and scalable enterprise applications using modern practices. He is a technology enthusiast and has a passion for coding & blogging.

Источник

Roy’s musings

Question: What is the most efficient way of creating a collection (Set, List or Map) with a single element?

  • Collections.singleton — To create a set that has only one element.
  • Collections.singletonList — To create a list that has only one element.
  • Collections.singletonMap — To crate a map that has only one entry.

Compare these methods with Collections.unmodifiableXXX() methods. The umodifiableXXX methods already accept a collection as an argument.

  • Get link
  • Facebook
  • Twitter
  • Pinterest
  • Email
  • Other Apps

Comments

A note on Java’s Calendar set() method

Remember that the Calendar’s internal fields include year, month, date, hour, minutes, seconds, milliseconds and time zone. Whenever you are calling a set() method with multiple fields, like set(year, month, date), it will not affect the rest of the fields. Remember that there is no set() method with multiple fields available to set the milliseconds. If you would like to set the milliseconds, you must use set(Calendar.MILLISECOND, value). Likewise, if you are planning to set all the fields, its a good idea to reset all the fields using clear() method. This will clear milliseconds as well. Most of the times, millisecond field may not be of interest to you. But if you are going to use the UTC milliseconds, by calling getTimeInMillis(), then make sure you set the right values for milliseconds as well.

The mysterious ORA-03111 error

Recently one of the applications that I developed started throwing exceptions, that had the following message: SQL state [72000]; error code [1013]; ORA-03111: break received on communication channel When I googled around, I couldn’t come across anything useful. Sadly enough most of the sites just showed the documentation for that error, without any explanation from anyone experiencing that issues. So here you go, with the best possible explanation that I could come up with. My application sets two things on the connection that is throwing this exception: It sets the fetchSize to be 2500 rows It sets the query timeout to be 10 seconds The database server and the application are separated over a long latency network (actually there is a NetEm box that emulates the long latency between these two boxes) which has a latency characteristic of 50+/-5 milliseconds. This is the whole setup. It is important to understand how the timeout is handled by the Oracle client (in my case JDBC clien

Note on allocationSize parameter of @SequenceGenerator while using JPA

I ran into what I thought as an issue while I was using the sequence ID generation strategy in JPA. The JPA provider I am using is Hibernate. I think sharing my experience will save someone some time. To use a sequence (For e.g. Oracle sequence) to generate values and assign them to the ID field of your persistence object, you will following something like this: @Id @Column(name = «ITEM_ID») @GeneratedValue(strategy = GenerationType.SEQUENCE, generator=»ItemIdSeqGenerator») @SequenceGenerator(name=»ItemIdSeqGenerator», sequenceName=»ITEM_ID_SEQ», allocationSize=1) private long itemId; This means the following things: The @Id annotation says that the field itemId is a primary key. The @Column annotation says that the corresponding column in the database is ITEM_ID. The @GeneratedValue says that the value that needs to be populated in the itemId should be generated, while that object is persisted. The strategy to generate the value is to

Источник

Читайте также:  Python module how to make
Оцените статью