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 { NORTH, SOUTH, EAST, WEST }
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:
@Test public void operations() { EnumMap<Direction, String> map = Maps.newEnumMap(Direction.class); //increase map.put(Direction.EAST, "east"); map.put(Direction.SOUTH, "south"); map.put(Direction.WEST, "west"); //query assertTrue(map.containsKey(Direction.EAST)); assertFalse(map.containsKey(Direction.NORTH)); //delete map.remove(Direction.EAST); assertFalse(map.containsKey(Direction.EAST)); assertFalse(map.remove(Direction.WEST, "north")); assertTrue(map.remove(Direction.WEST, "west")); //empty map.clear(); 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(); values.forEach(System.out::println); //Return all keys Set<Direction> keySet = map.keySet(); keySet.forEach(System.out::println); //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:
north south east west NORTH SOUTH EAST WEST NORTH:North SOUTH:South EAST:East WEST:West
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 values.remove("east"); assertEquals(3, map.size()); assertEquals(3, keySet.size()); assertEquals(3, entrySet.size()); keySet.remove(Direction.WEST); 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 map.clear(); 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.