新聞中心
前言

最近幾天看了幾篇有關(guān)于Java Map的外國(guó)博文,寫得非常不錯(cuò),所以整理了Java map 應(yīng)該掌握的8個(gè)問(wèn)題,都是日常開發(fā)司空見(jiàn)慣的問(wèn)題,希望對(duì)大家有幫助;如果有不正確的地方,歡迎提出,萬(wàn)分感謝哈~
本章節(jié)所有代碼demo已上傳github
1、如何把一個(gè)Map轉(zhuǎn)化為L(zhǎng)ist
日常開發(fā)中,我們經(jīng)常遇到這種場(chǎng)景,把一個(gè)Map轉(zhuǎn)化為L(zhǎng)ist。map轉(zhuǎn)List有以下三種轉(zhuǎn)化方式:
- 把map的鍵key轉(zhuǎn)化為list
- 把map的值value轉(zhuǎn)化為list
- 把map的鍵值key-value轉(zhuǎn)化為list
偽代碼如下:
- // 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());
示例代碼:
- public class Test {
- public static void main(String[] args) {
- Map
map = new HashMap<>(); - map.put(2, "jay");
- map.put(1, "whx");
- map.put(3, "huaxiao");
- //把一個(gè)map的鍵轉(zhuǎn)化為list
- List
keyList = new ArrayList<>(map.keySet()); - System.out.println(keyList);
- //把map的值轉(zhuǎn)化為list
- List
valueList = new ArrayList<>(map.values()); - System.out.println(valueList);
- 把map的鍵值轉(zhuǎn)化為list
- List entryList = new ArrayList(map.entrySet());
- System.out.println(entryList);
- }
- }
運(yùn)行結(jié)果:
- [1, 2, 3]
- [whx, jay, huaxiao]
- [1=whx, 2=jay, 3=huaxiao]
2、如何遍歷一個(gè)Map
我們經(jīng)常需要遍歷一個(gè)map,可以有以下兩種方式實(shí)現(xiàn):
通過(guò)entrySet+for實(shí)現(xiàn)遍歷
- for(Entry entry: map.entrySet()) {
- // get key
- K key = entry.getKey();
- // get value
- V value = entry.getValue();
- }
實(shí)例代碼:
- public class EntryMapTest {
- public static void main(String[] args) {
- Map
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);
- }
- }
- }
通過(guò)Iterator+while實(shí)現(xiàn)遍歷
- Iterator itr = map.entrySet().iterator();
- while(itr.hasNext()) {
- Entry entry = itr.next();
- // get key
- K key = entry.getKey();
- // get value
- V value = entry.getValue();
- }
實(shí)例代碼:
- public class IteratorMapTest {
- public static void main(String[] args) {
- Map
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);
- }
- }
- }
運(yùn)行結(jié)果:
- key:1,value:whx
- key:2,value:jay
- key:3,value:huaxiao
3、如何根據(jù)Map的keys進(jìn)行排序
對(duì)Map的keys進(jìn)行排序,在日常開發(fā)很常見(jiàn),主要有以下兩種方式實(shí)現(xiàn)。
把Map.Entry放進(jìn)list,再用Comparator對(duì)list進(jìn)行排序
- List list = new ArrayList(map.entrySet());
- Collections.sort(list, (Entry e1, Entry e2)-> {
- return e1.getKey().compareTo(e2.getKey());
- });
實(shí)例代碼:
- public class SortKeysMapTest {
- public static void main(String[] args) {
- Map
map = new HashMap<>(); - map.put("2010", "jay");
- map.put("1999", "whx");
- map.put("3010", "huaxiao");
- List
> 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());
- }
- }
- }
使用SortedMap+TreeMap+Comparator實(shí)現(xiàn)
- 1. SortedMap sortedMap = new TreeMap(new Comparator() {
- 2. @Override
- 3. public int compare(K k1, K k2) {
- 4. return k1.compareTo(k2);
- 5. }
- 6. });
- 7. sortedMap.putAll(map);
實(shí)例代碼:
- public class SortKeys2MapTest {
- public static void main(String[] args) {
- Map
map = new HashMap<>(); - map.put("2010", "jay");
- map.put("1999", "whx");
- map.put("3010", "huaxiao");
- SortedMap sortedMap = new TreeMap(new Comparator
() { - @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);
- }
- }
- }
運(yùn)行結(jié)果:
- key:1999,value:whx
- key:2010,value:jay
- key:3010,value:huaxiao
4、如何對(duì)Map的values進(jìn)行排序
- List list = new ArrayList(map.entrySet());
- Collections.sort(list, (Entry e1, Entry e2) ->{
- return e1.getValue().compareTo(e2.getValue());
- });
實(shí)例代碼:
- public class SortValuesMapTest {
- public static void main(String[] args) {
- Map
map = new HashMap<>(); - map.put("2010", "jay");
- map.put("1999", "whx");
- map.put("3010", "huaxiao");
- List
>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());
- }
- }
- }
運(yùn)行結(jié)果:
- key:3010,value:huaxiao
- key:2010,value:jay
- key:1999,value:whx
5、如何初始化一個(gè)靜態(tài)/不可變的Map
初始化一個(gè)靜態(tài)不可變的map,單單static final+static代碼塊還是不行的,如下:
- public class Test1 {
- private static final Map
map; - static {
- map = new HashMap
(); - 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);
- }
- }
- }
這里面,map繼續(xù)添加元素(3,"three"),發(fā)現(xiàn)是OK的,運(yùn)行結(jié)果如下:
- key:1,value:one
- key:2,value:two
- key:3,value:three
真正實(shí)現(xiàn)一個(gè)靜態(tài)不可變的map,需要Collections.unmodifiableMap,代碼如下:
- public class Test2 {
- private static final Map
map; - static {
- Map
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);
- }
- }
- }
運(yùn)行結(jié)果如下:
可以發(fā)現(xiàn),繼續(xù)往map添加元素是會(huì)報(bào)錯(cuò)的,實(shí)現(xiàn)真正不可變的map。
6、HashMap, TreeMap, and Hashtable,ConcurrentHashMap的區(qū)別
7、如何創(chuàng)建一個(gè)空map
如果map是不可變的,可以這樣創(chuàng)建:
- Map map=Collections.emptyMap();
- or
- Map
map=Collections. emptyMap(); - //map1.put("1", "1"); 運(yùn)行出錯(cuò)
如果你希望你的空map可以添加元素的,可以這樣創(chuàng)建
- Map map = new HashMap();
8、有關(guān)于map的復(fù)制
有關(guān)于hashmap的復(fù)制,在日常開發(fā)中,使用也比較多。主要有 =,clone,putAll,但是他們都是淺復(fù)制,使用的時(shí)候注意啦,可以看一下以下例子:
例子一,使用=復(fù)制一個(gè)map:
- public class CopyMapAssignTest {
- public static void main(String[] args) {
- Map
userMap = new HashMap<>(); - userMap.put(1, new User("jay", 26));
- userMap.put(2, new User("fany", 25));
- //Shallow clone
- Map
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);
- }
- }
運(yùn)行結(jié)果:
- {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}}
從運(yùn)行結(jié)果看出,對(duì)cloneMap修改,兩個(gè)map都改變了,所以=是淺復(fù)制。
例子二,使用hashmap的clone復(fù)制:
- {
- public static void main(String[] args) {
- HashMap
userMap = new HashMap<>(); - userMap.put(1, new User("jay", 26));
- userMap.put(2, new User("fany", 25));
- //Shallow clone
- HashMap
clonedMap = (HashMap ) 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);
- }
- }
運(yùn)行結(jié)果:
- {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}}
從運(yùn)行結(jié)果看出,對(duì)cloneMap修改,兩個(gè)map都改變了,所以hashmap的clone也是淺復(fù)制。
例子三,通過(guò)putAll操作
- public class CopyPutAllMapTest {
- public static void main(String[] args) {
- HashMap
userMap = new HashMap<>(); - userMap.put(1, new User("jay", 26));
- userMap.put(2, new User("fany", 25));
- //Shallow clone
- HashMap
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);
- }
- }
運(yùn)行結(jié)果:
- {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}}
從運(yùn)行結(jié)果看出,對(duì)cloneMap修改,兩個(gè)map都改變了,所以putAll還是淺復(fù)制。
那么,如何實(shí)現(xiàn)深度復(fù)制呢?
可以使用序列化實(shí)現(xiàn),如下為谷歌Gson序列化HashMap,實(shí)現(xiàn)深度復(fù)制的例子:
- public class CopyDeepMapTest {
- public static void main(String[] args) {
- HashMap
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
>(){}.getType(); - HashMap
clonedMap = gson.fromJson(jsonString, type); - //Same as userMap
- System.out.println(clonedMap);
- System.out.println("\nChanges reflect in only one 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);
- }
- }
運(yùn)行結(jié)果:
- {1=User{name='jay', age=26}, 2=User{name='fany', age=25}}
- Changes reflect in only one 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}}
從運(yùn)行結(jié)果看出,對(duì)cloneMap修改,userMap沒(méi)有被改變,所以是深度復(fù)制。
文章標(biāo)題:有關(guān)于JavaMap,應(yīng)該掌握的8個(gè)問(wèn)題
文章源于:http://www.dlmjj.cn/article/djocsgs.html


咨詢
建站咨詢
