HashMap performs well?Asked me if EnumMap did not

Keywords: Java JDK

1 Introduction

We know that Map is just an interface and has many implementations. HashMap is the most common one in Java.This article is about another implementation: EnumMap.It is an enumerated Map, requiring its Key values to be enumerated.

2 Create your EnumMap

Now that it's a Map about the enumeration type, let's first create an enumeration for later use:

public enum Directions {

2.1 Three ways to create EnumMap

JDK provides three ways to create an EnumMap with the following code:

//new EnumMap
EnumMap<Direction, String> enumMap = new EnumMap<>(Direction.class);
enumMap.put(Direction.EAST, "east");
enumMap.put(Direction.SOUTH, "south");
//Copy from EnumMap
EnumMap<Direction, String> enumMapCopyEnumMap = new EnumMap<>(enumMap);
assertEquals(enumMap, enumMapCopyEnumMap);
//Copy from Map
Map<Direction, String> hashMap = Maps.newHashMap();
hashMap.put(Direction.EAST, "east");
hashMap.put(Direction.SOUTH, "south");
EnumMap<Direction, String> enumMapCopyHashMap = new EnumMap<>(hashMap);
assertEquals(enumMap, enumMapCopyHashMap);
  • (1) When using the new EnumMap() method, unlike HashMap, it must pass in an enumerated type to create an object;
  • (2) Copy from EnumMap, where the parameter passed in is EnumMap;
  • (3) Copy from Map, the parameter passed in is Map, but the type of Key must be enumerated.

2.2 Smart Guava

In fact, you can combine the above three cases, but actually there are two methods:

  • (1) Use new EnumMap (Class <K> keyType)
  • (2) Use new EnumMap (Map<K,? Extends V> m)

The smart Guava offers only these two methods, as follows:

//Create with Guava
EnumMap<Direction, String> enumMapGuava = Maps.newEnumMap(Direction.class);
enumMapGuava.put(Direction.SOUTH, "south");
assertEquals(1, enumMapGuava.size());
enumMapGuava = Maps.newEnumMap(enumMap);
assertEquals(enumMap, enumMapGuava);

3 Basic operations

The method provided is, of course, the same as Map, which is very convenient to use, and the code is as follows:

public void operations() {
  EnumMap<Direction, String> map = Maps.newEnumMap(Direction.class);
  map.put(Direction.EAST, "east");
  map.put(Direction.SOUTH, "south");
  map.put(Direction.WEST, "west");
  assertFalse(map.remove(Direction.WEST, "north"));
  assertTrue(map.remove(Direction.WEST, "west"));
  assertEquals(0, map.size());

It is important to note that the deletion method passes in two parameters, Key and Value. map.remove(Direction.WEST,'West') succeeds when a key-value pair matches, and map.remove(Direction.WEST,'North') fails without deleting.

4 Collection View

4.1 Orderability

EnumMap can return all of its Values, Keys, Entry, and so on, just like the capabilities provided by the Map interface.Unlike HashMap, however, EnumMap returns an ordered view, which is not the order of insertion but the order of enumeration definitions.The code is as follows:

EnumMap<Direction, String> map = Maps.newEnumMap(Direction.class);
map.put(Direction.EAST, "east");
map.put(Direction.SOUTH, "south");
map.put(Direction.WEST, "west");
map.put(Direction.NORTH, "north");
//Return all Value s
Collection<String> values = map.values();
//Return all keys
Set<Direction> keySet = map.keySet();
//Return all <Key, Value>
Set<Map.Entry<Direction, String>> entrySet = map.entrySet();
entrySet.forEach(entry -> {
  System.out.println(entry.getKey() + ":" + entry.getValue());

The output is as follows:


This order is really the same as the order in which we define enumerations, not the order in which they are added.

4.2 Linkage

In addition to orderliness, the collection view returned by EnumMap is one thing different from linkage, which is all-in-one.Change one and the other.Just look at the code to see:

//Values, keySet, entrySet changes affect other
assertEquals(3, map.size());
assertEquals(3, keySet.size());
assertEquals(3, entrySet.size());

assertEquals(2, map.size());
assertEquals(2, values.size());
assertEquals(2, entrySet.size());

entrySet.removeIf(entry -> Objects.equals(entry.getValue(), "north"));
assertEquals(1, map.size());
assertEquals(1, keySet.size());
assertEquals(1, values.size());

//Map changes affect other views
assertEquals(0, values.size());
assertEquals(0, keySet.size());
assertEquals(0, entrySet.size());

5 Performance

Performance is one of the main reasons we choose EnumMap, so why does it perform better than a good HashMap?You can tell by looking at the source code:

(1) The bottom layer stores data through two arrays, one Keys and one Values;

(2) Because the Key value is an enumeration type, that is, the number of elements is determined at the beginning, when an EnumMap is created, the size of the array holding the data is determined, regardless of the performance implications of subsequent enlargements.

(3) Enumerations themselves are fixed-order and can be ordered by the Enum.ordinal() method, which can be used as an index for queries and inserts rather than calculating HashCode, and performance will be faster.This order is the array subscript.This is why EnumMap's collection views are ordered.

(4) Because the size is fixed, load factors are not considered, hash conflicts are not encountered, and the spatial complexity is small.

6 Conclusion

This paper introduces the creation, use, set view, and performance analysis of EnumMap as a special implementation of Map and finds that it is somebody else's fault.When our Key values are enumerated, try EnumMap for better performance.

Welcome to Public Number <Pumpkin Slow>, it will be updated for you continuously.

Read more, share more; write more, organize more.

Posted by alen on Thu, 07 Nov 2019 06:17:37 -0800