Preface
I have read several foreign blogs about Java map in the last few days and have written very well, so I have sorted out eight issues that Java map should master, which are common problems in daily development. I hope they will help you. If there are any incorrect points, please mention them. Thank you very much.
1. How to convert a Map into a List
In daily development, we often encounter this scenario, converting a Map into a List. Map to List can be converted in three ways:
- Convert map key to list
- Convert map's value value value to list
- Convert map key-value to list
The pseudocode is as follows:
// key list List keyList = new ArrayList(map.keySet()); // value list List valueList = new ArrayList(map.values()); // key-value list List entryList = new ArrayList(map.entrySet());
Sample code:
public class Test { public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); map.put(2, "jay"); map.put(1, "whx"); map.put(3, "huaxiao"); //Convert a map's key to a list List<Integer> keyList = new ArrayList<>(map.keySet()); System.out.println(keyList); //Convert map values to list s List<String> valueList = new ArrayList<>(map.values()); System.out.println(valueList); hold map The key value of list List entryList = new ArrayList(map.entrySet()); System.out.println(entryList); } }
Run result:
[1, 2, 3] [whx, jay, huaxiao] [1=whx, 2=jay, 3=huaxiao]
2. How to traverse a Map
We often need to traverse a map, which can be implemented in two ways:
Traversal through entrySet+for
for(Entry entry: map.entrySet()) { // get key K key = entry.getKey(); // get value V value = entry.getValue(); }
Instance code:
public class EntryMapTest { public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); map.put(2, "jay"); map.put(1, "whx"); map.put(3, "huaxiao"); for(Map.Entry entry: map.entrySet()) { // get key Integer key = (Integer) entry.getKey(); // get value String value = (String) entry.getValue(); System.out.println("key:"+key+",value:"+value); } } }
Traversal through Iterator+while
Iterator itr = map.entrySet().iterator(); while(itr.hasNext()) { Entry entry = itr.next(); // get key K key = entry.getKey(); // get value V value = entry.getValue(); }
Instance code:
public class IteratorMapTest { public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); map.put(2, "jay"); map.put(1, "whx"); map.put(3, "huaxiao"); Iterator itr = map.entrySet().iterator(); while(itr.hasNext()) { Map.Entry entry = (Map.Entry) itr.next(); // get key Integer key = (Integer) entry.getKey(); // get value String value = (String) entry.getValue(); System.out.println("key:"+key+",value:"+value); } } }
Run result:
key:1,value:whx key:2,value:jay key:3,value:huaxiao
3. How to sort by Map's keys
Sorting the keys of a Map is common in everyday development and is implemented in two main ways.
Put Map.Entry into the list, and then use Comparator to sort the list
List list = new ArrayList(map.entrySet()); Collections.sort(list, (Entry e1, Entry e2)-> { return e1.getKey().compareTo(e2.getKey()); });
Instance code:
public class SortKeysMapTest { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("2010", "jay"); map.put("1999", "whx"); map.put("3010", "huaxiao"); List<Map.Entry<String,String>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (Map.Entry e1, Map.Entry e2)-> { return e1.getKey().toString().compareTo(e2.getKey().toString()); }); for (Map.Entry entry : list) { System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue()); } } }
Implement with SortedMap+TreeMap+Comparator
SortedMap sortedMap = new TreeMap(new Comparator() { @Override public int compare(K k1, K k2) { return k1.compareTo(k2); } }); sortedMap.putAll(map);
Instance code:
public class SortKeys2MapTest { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("2010", "jay"); map.put("1999", "whx"); map.put("3010", "huaxiao"); SortedMap sortedMap = new TreeMap(new Comparator<String>() { @Override public int compare(String k1, String k2) { return k1.compareTo(k2); } }); sortedMap.putAll(map); Iterator itr = sortedMap.entrySet().iterator(); while(itr.hasNext()) { Map.Entry entry = (Map.Entry) itr.next(); // get key String key = (String) entry.getKey(); // get value String value = (String) entry.getValue(); System.out.println("key:"+key+",value:"+value); } } }
Run result:
key:1999,value:whx key:2010,value:jay key:3010,value:huaxiao
4. How to sort the values of a Map
List list = new ArrayList(map.entrySet()); Collections.sort(list, (Entry e1, Entry e2) ->{ return e1.getValue().compareTo(e2.getValue()); });
Instance code:
public class SortValuesMapTest { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("2010", "jay"); map.put("1999", "whx"); map.put("3010", "huaxiao"); List <Map.Entry<String,String>>list = new ArrayList<>(map.entrySet()); Collections.sort(list, (Map.Entry e1, Map.Entry e2)-> { return e1.getValue().toString().compareTo(e2.getValue().toString()); } ); for (Map.Entry entry : list) { System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue()); } } }
Run result:
key:3010,value:huaxiao key:2010,value:jay key:1999,value:whx
5. How to initialize a static/immutable Map
Initializing a static immutable map does not work with static final+static code alone, as follows:
public class Test1 { private static final Map <Integer,String>map; static { map = new HashMap<Integer, String>(); map.put(1, "one"); map.put(2, "two"); } public static void main(String[] args) { map.put(3, "three"); Iterator itr = map.entrySet().iterator(); while(itr.hasNext()) { Map.Entry entry = (Map.Entry) itr.next(); // get key Integer key = (Integer) entry.getKey(); // get value String value = (String) entry.getValue(); System.out.println("key:"+key+",value:"+value); } } }
Here, map continues to add elements (3,'three') and finds that it is OK. The results are as follows:
key:1,value:one key:2,value:two key:3,value:three
Collections are required to truly implement a static and immutable map. UnmodifiableMap, code as follows:
public class Test2 { private static final Map<Integer, String> map; static { Map<Integer,String> aMap = new HashMap<>(); aMap.put(1, "one"); aMap.put(2, "two"); map = Collections.unmodifiableMap(aMap); } public static void main(String[] args) { map.put(3, "3"); Iterator itr = map.entrySet().iterator(); while(itr.hasNext()) { Map.Entry entry = (Map.Entry) itr.next(); // get key Integer key = (Integer) entry.getKey(); // get value String value = (String) entry.getValue(); System.out.println("key:"+key+",value:"+value); } } }
You can find that it is wrong to continue adding elements to the map to achieve a truly immutable map.
6. Differences between HashMap, TreeMap, Hashtable, ConcurrentHashMap
HashMap | TreeMap | Hashtable | ConcurrentHashMap | |
---|---|---|---|---|
Orderliness | no | yes | no | no |
null k-v | Yes-Yes | No-Yes | No-No | No-No |
Linear security | no | no | yes | yes |
Time Complexity | O(1) | O(log n) | O(1) | O(log n) |
Underlying structure | Array+Chain List+Red-Black Tree | red-black tree | Array+Chain List | Array+Chain List+Red-Black Tree |
7. How to create an empty map
If the map is immutable, you can create it as follows:
Map map=Collections.emptyMap(); or Map<String,String> map=Collections.<String, String>emptyMap(); //map1.put("1", "1"); Run Error
If you want your empty map to add elements, you can create one like this
Map map = new HashMap();
8. Replication about map s
Replication of hashmap is also used in daily development. The main ones are=, clone, putAll, but they are all shallow copies, so be careful when you use them. Here are some examples:
Example 1, use = to copy a map:
public class CopyMapAssignTest { public static void main(String[] args) { Map<Integer, User> userMap = new HashMap<>(); userMap.put(1, new User("jay", 26)); userMap.put(2, new User("fany", 25)); //Shallow clone Map<Integer, User> clonedMap = userMap; //Same as userMap System.out.println(clonedMap); System.out.println("\nChanges reflect in both maps \n"); //Change a value is clonedMap clonedMap.get(1).setName("test"); //Verify content of both maps System.out.println(userMap); System.out.println(clonedMap); } }
Run result:
{1=User{name='jay', age=26}, 2=User{name='fany', age=25}} Changes reflect in both maps {1=User{name='test', age=26}, 2=User{name='fany', age=25}} {1=User{name='test', age=26}, 2=User{name='fany', age=25}}
As you can see from the running results, both map s have changed for the cloneMap modification, so = shallow copy.
Example 2, clone replication using hashmap:
public class CopyCloneMapTest { public static void main(String[] args) { HashMap<Integer, User> userMap = new HashMap<>(); userMap.put(1, new User("jay", 26)); userMap.put(2, new User("fany", 25)); //Shallow clone HashMap<Integer, User> clonedMap = (HashMap<Integer, User>) userMap.clone(); //Same as userMap System.out.println(clonedMap); System.out.println("\nChanges reflect in both maps \n"); //Change a value is clonedMap clonedMap.get(1).setName("test"); //Verify content of both maps System.out.println(userMap); System.out.println(clonedMap); } }
Run result:
{1=User{name='jay', age=26}, 2=User{name='fany', age=25}} Changes reflect in both maps {1=User{name='test', age=26}, 2=User{name='fany', age=25}} {1=User{name='test', age=26}, 2=User{name='fany', age=25}}
As you can see from the running results, both map s have changed with the cloneMap modification, so the clone of hashmap is also a shallow copy.
Example 3, using the putAll operation
public class CopyPutAllMapTest { public static void main(String[] args) { HashMap<Integer, User> userMap = new HashMap<>(); userMap.put(1, new User("jay", 26)); userMap.put(2, new User("fany", 25)); //Shallow clone HashMap<Integer, User> clonedMap = new HashMap<>(); clonedMap.putAll(userMap); //Same as userMap System.out.println(clonedMap); System.out.println("\nChanges reflect in both maps \n"); //Change a value is clonedMap clonedMap.get(1).setName("test"); //Verify content of both maps System.out.println(userMap); System.out.println(clonedMap); } }
Run result:
{1=User{name='jay', age=26}, 2=User{name='fany', age=25}} Changes reflect in both maps {1=User{name='test', age=26}, 2=User{name='fany', age=25}} {1=User{name='test', age=26}, 2=User{name='fany', age=25}}
As you can see from the running results, both map s have changed with the cloneMap modification, so putAll is still a shallow copy.
So how do you implement deep replication?
You can use serialization as an example of a deep copy by serializing HashMap for Google Gson:
public class CopyDeepMapTest { public static void main(String[] args) { HashMap<Integer, User> userMap = new HashMap<>(); userMap.put(1, new User("jay", 26)); userMap.put(2, new User("fany", 25)); //Shallow clone Gson gson = new Gson(); String jsonString = gson.toJson(userMap); Type type = new TypeToken<HashMap<Integer, User>>(){}.getType(); HashMap<Integer, User> clonedMap = gson.fromJson(jsonString, type); //Same as userMap System.out.println(clonedMap); System.out.println("\nChanges DO NOT reflect in other map \n"); //Change a value is clonedMap clonedMap.get(1).setName("test"); //Verify content of both maps System.out.println(userMap); System.out.println(clonedMap); } }
Run result:
{1=User{name='jay', age=26}, 2=User{name='fany', age=25}} Changes DO NOT reflect in other map {1=User{name='jay', age=26}, 2=User{name='fany', age=25}} {1=User{name='test', age=26}, 2=User{name='fany', age=25}}
As you can see from the running results, the userMap is not changed for the cloneMap modification, so it is a deep copy.