关于Java Map,你应该掌握哪8个问题?

关于Java Map,你应该掌握哪8个问题?

前言

最近几天看了几篇有关于Java Map的外国博文,写得非常不错,所以整理了Java map 应该掌握的8个问题,都是日常开发司空见惯的问题,希望对大家有帮助;如果有不正确的地方,欢迎提出,万分感谢哈~

本章节所有代码demo已上传github

1、如何把一个Map转化为List

日常开发中,我们经常遇到这种场景,把一个Map转化为List。map转List有以下三种转化方式:

  • 把map的键key转化为list
  • 把map的值value转化为list
  • 把map的键值key-value转化为list

伪代码如下:

// key listList keyList = new ArrayList(map.keySet());// value listList valueList = new ArrayList(map.values());// key-value listList 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"); //把一个map的键转化为list List keyList = new ArrayList<>(map.keySet()); System.out.println(keyList); //把map的值转化为list List valueList = new ArrayList<>(map.values()); System.out.println(valueList); 把map的键值转化为list List entryList = new ArrayList(map.entrySet()); System.out.println(entryList); }}

运行结果:

[1, 2, 3][whx, jay, huaxiao][1=whx, 2=jay, 3=huaxiao]

2、如何遍历一个Map

我们经常需要遍历一个map,可以有以下两种方式实现:

通过entrySet+for实现遍历

for(Entry entry: map.entrySet()) {  // get key  K key = entry.getKey();  // get value  V value = entry.getValue();}

实例代码:

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);        }    }}

通过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();}

实例代码:

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);        }    }}

运行结果:

key:1,value:whxkey:2,value:jaykey:3,value:huaxiao

3、如何根据Map的keys进行排序

对Map的keys进行排序,在日常开发很常见,主要有以下两种方式实现。

把Map.Entry放进list,再用Comparator对list进行排序

List list = new ArrayList(map.entrySet());Collections.sort(list, (Entry e1, Entry e2)-> {    return e1.getKey().compareTo(e2.getKey());});

实例代码:

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实现

SortedMap sortedMap = new TreeMap(new Comparator() {  @Override  public int compare(K k1, K k2) {    return k1.compareTo(k2);  }});sortedMap.putAll(map);

实例代码:

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);        }    }}

运行结果:

key:1999,value:whxkey:2010,value:jaykey:3010,value:huaxiao

4、如何对Map的values进行排序

List list = new ArrayList(map.entrySet());Collections.sort(list, (Entry e1, Entry e2) ->{    return e1.getValue().compareTo(e2.getValue());  });

实例代码:

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());        }    }}

运行结果:

key:3010,value:huaxiaokey:2010,value:jaykey:1999,value:whx

5、如何初始化一个静态/不可变的Map

初始化一个静态不可变的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继续添加元素(3,"three"),发现是OK的,运行结果如下:

key:1,value:onekey:2,value:twokey:3,value:three

真正实现一个静态不可变的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);        }    }复制代码

运行结果如下:


关于Java Map,你应该掌握哪8个问题?

可以发现,继续往map添加元素是会报错的,实现真正不可变的map。

6、HashMap, TreeMap, and Hashtable,ConcurrentHashMap的区别

HashMap TreeMap Hashtable ConcurrentHashMap 有序性 否 是 否 否 null k-v 是-是 否-是 否-否 否-否 线性安全 否 否 是 是 时间复杂度 O(1) O(log n) O(1) O(log n) 底层结构 数组+链表 红黑树 数组+链表 红黑树

7、如何创建一个空map

如果map是不可变的,可以这样创建:

Map map=Collections.emptyMap();orMap map=Collections.emptyMap();//map1.put("1", "1"); 运行出错

如果你希望你的空map可以添加元素的,可以这样创建

Map map = new HashMap();

8、有关于map的复制

有关于hashmap的复制,在日常开发中,使用也比较多。主要有=,clone,putAll,但是他们都是浅复制,使用的时候注意啦,可以看一下以下例子:

例子一,使用=复制一个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);    }}

运行结果:

{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}}

从运行结果看出,对cloneMap修改,两个map都改变了,所以=是浅复制。

例子二,使用hashmap的clone复制:

public class CopyCloneMapTest {    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);    }}

运行结果:

{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}}

从运行结果看出,对cloneMap修改,两个map都改变了,所以hashmap的clone也是浅复制。

例子三,通过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);    }}

运行结果:

{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}}

从运行结果看出,对cloneMap修改,两个map都改变了,所以putAll还是浅复制。

那么,如何实现深度复制呢?

可以使用序列化实现,如下为谷歌Gson序列化HashMap,实现深度复制的例子:

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 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);    }}

运行结果:

{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}}

从运行结果看出,对cloneMap修改,userMap没有被改变,所以是深度复制。

作者:Jay_huaxiao
链接:https://juejin.im/post/5e36f832e51d454d523beb70


分享到:


相關文章: